hdu4983 Goffi and GCD(欧拉函数+思维)(好题)

题目链接
Problem Description
Goffi is doing his math homework and he finds an equality on his text book: gcd(n−a,n)×gcd(n−b,n)=nk.

Goffi wants to know the number of (a,b) satisfy the equality, if n and k are given and 1≤a,b≤n.

Note: gcd(a,b) means greatest common divisor of a and b.

Input
Input contains multiple test cases (less than 100). For each test case, there’s one line containing two integers n and k (1≤n,k≤109).

Output
For each test case, output a single integer indicating the number of (a,b) modulo 109+7.

Sample Input
2 1
3 2

Sample Output
2
1
Hint
For the first case, (2, 1) and (1, 2) satisfy the equality.

思路:一开始看到这个式子被吓到了,其实就是长得吓人,仔细思考一下。首先等式的两个gcd最大值肯定不超过n,所以n大于2的直接为0,n等于2的时候只有一种可能就是两个都为n(因为你想想两个数相乘要为n^2,两个都比n小的数是不可能成为n平方的,所以只有nn),剩下的就是k等于1的时候了,这时候又体现了欧拉的神奇之处了,我们设gcd(n-a,n)为x,那么等于是不是就等于gcd(n-a/x,n/x)要想找到满足条件的a的话答案就是就是枚举n的因子求它的欧拉函数(由于并没有要我们求出具体a和b,只要求个数就行了,那么直接欧拉函数就行了),gcd(n-b,n)也是同理,根据乘法原理,答案为两边相乘再乘2,只要注意一下ii==n的时候两边会重复计算,特判一下就行。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll get_euler(ll n){ 
    ll res=n,a=n;
    for (ll i = 2; i*i<=a;i++){
        if(a%i==0){
            res=res/i*(i-1);
            while(a%i==0) a=a/i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}
int main()
{
    ll n,k;
    while(scanf("%lld %lld",&n,&k)!=EOF)
    {
        ll ans=0;
            if(n==1){
            printf("1\n");continue;
        }
        if(k>2) {
            printf("0\n");continue;
        }
        if(k==2){
            printf("1\n");continue;
        }
        if(k==1){
            for(ll i=1;i*i<=n;++i)
        {
            if(n%i==0)
            {
                if(i*i==n) ans+=get_euler(n/i)*get_euler(i);
                else ans+=2*get_euler(n/i)*get_euler(i);
                ans%=mod;
            }
        }
        }
        printf("%lld\n",ans);
    }
 } 
发布了283 篇原创文章 · 获赞 0 · 访问量 7322

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104998255