您的位置:首页 > 编程语言 > Go语言

bc第六场Goffi and GCD

2015-07-31 17:17 190 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=52936

题意:要求找满足条件的a,b有多少种,条件是:gcd(n-a,n)*gcd(n-b,n)=n的k次方,其中a,b均满足1<=a,b<=n

思路:新学的欧拉函数,这个函数euler(n)是用来寻找n前面有多少个与n互质的数。在本题中,讲条件转化一下就是:gcd(n-a,n)=x,gcd(n-b,n)=n/x,其中x是n的因子,每个a对应一个n-a,那么也就可以转换成:gcd(a,n)=x,gcd(b,n)=n/x。观察容易发现:gcd(a/x,n/x)=1,也就是a/x,与n/x互质,问有多少个a(0<a<=n-1),那么就是问n/x前面有多少个数字与n/x互质,就是直接调用欧拉函数

代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#define maxn 100005
using namespace std;
#define  ll  long long
#define mod  1000000007
ll euler(ll x)
{
ll res = x;
for (ll i = 2; i <= x / i; i++)
if (x % i == 0)
{
res = res / i * (i - 1);
while(x % i == 0) x /= i;
}
if (x > 1) res = res / x * (x - 1);
return res;
}

int main()
{
ll n,k;
int cnt;
ll sum;
ll x,y;
ll ans[maxn];
while(scanf("%I64d%I64d",&n,&k)!=EOF)
{
if(n==1)
{
printf("1\n");
continue;
}
if(k>2)
{
printf("0\n");
continue;
}
if(k==2)
{
printf("1\n");
continue;
}

cnt=0;
memset(ans,0,sizeof(ans));
for(int i=1; i<=sqrt(n*1.0); i++)
{
if(n%i==0)
ans[cnt++]=i;
}
sum=0;
//cout<<cnt<<endl;
for(int i=0; i<cnt; i++)
{
if(n/ans[i]==ans[i])
{
x=euler(ans[i]);
y=x;

sum+=x*y;
sum=sum%mod;
}
else
{
x=euler(n/ans[i]);
y=euler(ans[i]);
//cout<<x<<" "<<y<<" ";
sum+=x*y*2;
sum=sum%mod;
}
}
printf("%I64d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: