bc第六场Goffi and GCD

来源:互联网 发布:氧气听书软件电脑版 编辑:程序博客网 时间:2024/05/24 23:16

题目链接: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 100005using namespace std;#define  ll  long long#define mod  1000000007ll 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;}


 

0 0
原创粉丝点击