HDU 6053 TrickGCD

来源:互联网 发布:淘宝优惠券推广 编辑:程序博客网 时间:2024/05/20 05:10

设g(i)为公约数是i的倍数的方案数,f(i)为公约数是i的方案数。
则:

g(n)=n|df(d)=i=1main

由莫比乌斯反演可得:
f(n)=n|dμ(dn)g(d)

n=1时:
f(1)=1dmaxμ(d)g(d)

所以得到答案:
ans=g(1)f(1)

代码:

#include<bits/stdc++.h>using namespace std;#define fi first#define se second#define pb push_back#define CLR(A, X) memset(A, X, sizeof(A))#define bitcount(X) __builtin_popcountll(X)#pragma comment(linker, "/STACK:102400000, 102400000")const double eps = 1e-10;int dcmp(double x) { if(fabs(x) < eps) return 0; return x<0?-1:1; }typedef long long LL;typedef pair<int, int> PII;const int N = 1e5+5;const LL MOD = 1e9+7;bool prime[N];int mu[N], a[N], p[N];LL f[N];void init() {    for(int i = 2; i < N; i++) prime[i] = 1;    int k = 0;    mu[1] = 1;    for(int i = 2; i < N; i++) {        if(prime[i]) { p[k++] = i; mu[i] = -1; }        for(int j = 0; j<k && i*p[j]<N; j++) {            prime[i*p[j]] = 0;            if(i%p[j] == 0) { mu[i*p[j]] = 0; break; }            mu[i*p[j]] = -mu[i];        }    }}LL qpow(LL a, LL b) {    LL ret = 1;    while(b) {        if(b & 1) ret = ret*a%MOD;        a = a*a%MOD;        b >>= 1;    }    return ret;}int main() {//    freopen("1009.in", "r", stdin);//    freopen("1009.out", "w", stdout);    init();    int T;    scanf("%d", &T);    while(T--) {        CLR(a, 0);        int n, x, mi = N, mx = 0;        scanf("%d", &n);        for(int i = 1; i <= n; i++) {            scanf("%d", &x);            a[x]++;            mi = min(mi, x);            mx = max(mx, x);        }        for(int i = 1; i <= mx; i++) a[i] += a[i-1];        LL ans = 0;        for(int i = 1; i <= mi; i++) if(mu[i]) {            f[i] = mu[i];            for(int j = 1, k = i-1; k <= mx; j++, k += i) {                int x = k+i;                if(x > mx) x = mx;                f[i] = f[i]*qpow(j, a[x]-a[k])%MOD;            }            (ans += f[i]+MOD) %= MOD;        }        static int cas = 0;        printf("Case #%d: %lld\n", ++cas, (f[1]-ans+MOD)%MOD);    }    return 0;}
原创粉丝点击