hdu6053TrickGCD(莫比烏斯反演)

參考:http://blog.csdn.net/u013632138/article/details/52250567

          http://blog.csdn.net/xlzhang223/article/details/76218088

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=2e5+10;
int t,n,miu[maxn],primes[maxn];ll a[maxn],num[maxn],ans,mi,mx;
bool vis[maxn];
void Mobuls(){
    miu[1]=1;
    int cnt=0;
    for(int i=2;i<maxn;i++){
        if(!vis[i]){
            primes[cnt++]=i;
            miu[i]=-1;
        }
        for(int j=0;j<cnt;j++){
            ll tmp=i*primes[j];
            if(tmp>maxn) break;
            vis[tmp]=1;
            if(i%primes[j]) miu[tmp]=-miu[i];
            else            break;
        }
    }
}
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(){
     Mobuls();
     scanf("%d",&t);
     for(int c=1;c<=t;c++){
        scanf("%d",&n);
        ans=mx=0,mi=maxn;
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++) scanf("%lld",&a[i]),num[a[i]]++,mi=min(mi,a[i]),mx=max(mx,a[i]);
        for(int i=maxn-10;i>=0;i--) num[i]+=num[i+1];
        for(int i=2;i<=mi;i++){
            ll tmp=-miu[i],cnt=1,p=i;
            while(p<=mx) tmp=(tmp*qpow(cnt++,num[p]-num[p+i]))%mod,p+=i;
            //printf("%lld\n",tmp);
            ans=(ans+tmp+mod)%mod;
        }
        printf("Case #%d: %lld\n",c,ans);
     }
}


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