自爆魂

博客园 首页 新随笔 联系 订阅 管理

http://acm.hdu.edu.cn/showproblem.php?pid=4983

求有多少对元组满足题目中的公式。

对于K=1的情况,等价于gcd(A, N) * gcd(B, N) = N,我们枚举 gcd(A, N) = g,那么gcd(B, N) = N / g。问题转化为统计满足 gcd(A, N) = g 的 A 的个数。这个答案就是 ɸ(N/g)
只要枚举 N 的 约数就可以了。答案是 Σɸ(N/g)*ɸ(g) g | N

暴力即可

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%I64d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
const int modo = 1e9 + 7;
int k;

LL euler_phi(LL n) {
    LL m = sqrt(n+0.5);
    LL ret = n;
    for (LL i = 2; i <= m; i++) {
        if (n % i == 0) {
            ret = ret / i * (i-1);
            while (n%i==0)
                n /= i;
            if(n == 1)
                break;
        }
    }

    if (n > 1)
        ret = ret / n * (n - 1);
    return ret;
}
LL n;
int main() {
//	int _;RD(_);while(_--){
//	    ;
//	}
    while(~RD2(n,k)){
        if(n == 1 || k == 2)
            puts("1");
        else if(k > 2)
            puts("0");
        else{
            LL ans = 0;
            LL m = sqrt(n + 0.5);
            for(LL i = 1;i <= m;++i){
                if(n % i == 0){
                    ans = (ans + euler_phi(i)*euler_phi(n/i)*2) % modo;
                }
            }
            if(m*m == n){
                ans = (ans + modo - euler_phi(m)*euler_phi(m)) % modo;
            }
            printf("%I64d\n",ans);
        }
    }
	return 0;
}


posted on 2014-10-18 23:40  自爆魂  阅读(149)  评论(0编辑  收藏  举报