bc第六場Goffi and GCD

題目鏈接: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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章