zoukankan      html  css  js  c++  java
  • HDU 4983 Goffi and GCD(欧拉函数模板)

    Problem Description:

    Goffi is doing his math homework and he finds an equality on his text book: gcd(na,n)×gcd(nb,n)=n^k.

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

    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 (1n,k109).
     
    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.
     
    欧拉函数(求出一个数n与1~n之间互质的个数):找到n的一个质因子i,那么1~n中与n的公约数是i的倍数的概率pi = 1/i,那么与n的公约数不是i的倍数(这些数可能就是与n互质的数)概率为1-pi,即(i-1)/i;那么当我们找到n所有的质因子时,1~n之间与n互质的概率就是所有(1-pi)的乘积,那么与n互质的个数就是:Eular(n)=n*(1-p1)*(1-p2)....(1-pi);
     
    LL Eular(LL n)
    {
        LL i, ans = n;
    
        for (i = 2; i*i <= n; i++)
        {
            if (n % i == 0)
            {
                ans -= ans/i;
    
                while (n % i == 0) n /= i;
            }
        }
    
        if (n > 1) ans -= ans/n;
    
        return ans;
    }

    题意:给出n和k,求出满足gcd(n-a,n)*gcd(n-b,n) == n^k的(a,b)个数,注意(1,2)和(2,1)是两种情况。

    1.由于gcd(n-a,n)的值肯定<=n,所以当k>2时不存在满足条件的(a,b);

    2.当k==2或者n==1时发现满足条件的(a,b)只有一种;

    3.所以重点考虑k==1的情况:首先1<a<=n,那么0<=n-a<n,又因为gcd(0,n)= n,gcd(n-1,n)= 1,所以n-a相当于在1~n中,那么原式就可以变成gcd(a,n)*gcd(b,n)== n,那么gcd(a,n)就是n的一个因子,记为i,那么gcd(b,n)= n/i,由gcd(a,n)= i可得gcd(a/i,n/i)= 1,即a/i与n/i互质,且a/i<=n/i,那么满足式子的a的个数就是1~n/i与n/i互质的个数。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<math.h>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    
    const int N=1e6+10;
    const int INF=0x3f3f3f3f;
    const int MOD=1e9+7;
    
    typedef long long LL;
    
    LL Eular(LL n)
    {
        LL i, ans = n;
    
        for (i = 2; i*i <= n; i++)
        {
            if (n % i == 0)
            {
                ans -= ans/i;
    
                while (n % i == 0) n /= i;
            }
        }
    
        if (n > 1) ans -= ans/n;
    
        return ans;
    }
    
    int main ()
    {
        LL n, k, ans, i, num;
    
        while (scanf("%lld %lld", &n, &k) != EOF)
        {
            ans = num = 0;
    
            if (k == 2 || n == 1) ans = 1;
            else if (k == 1)
            {
                for (i = 1; i*i <= n; i++)
                {
                    if (n % i == 0)
                    {
                        if (i*i != n) ans = (ans + Eular(n/i)*Eular(i)*2) % MOD; ///因为当i*i!=n时,满足情况的a和b不一样,需要乘2
                        else ans = ans = (ans + Eular(n/i)*Eular(i)) % MOD;
                    }
                }
            }
    
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    Linux useradd 命令介绍
    lsscsi
    安装MegaCli,查看linux服务器raid信息
    ipmitool命令详解
    python 收发邮件
    angularjs 高级玩法 创建递归的模板
    我的Android进阶之旅------&gt;Android Activity的singleTask载入模式和onActivityResult方法之间的冲突
    Git实战(三)环境搭建
    使用Samba实现Linux与Windows文件共享实践
    设计模式个人备忘(享元模式,strategy, templete strategy)
  • 原文地址:https://www.cnblogs.com/syhandll/p/4917051.html
Copyright © 2011-2022 走看看