HDU 6053 TrickGCD

来源:互联网 发布:北津学院教务网络 编辑:程序博客网 时间:2024/05/20 02:26

和莫比乌斯反演类似
数组开小了会TLE,原因是数组越界访问可能会修改循环的判断值

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <bitset>#include <string>using namespace std;typedef long long LL;LL mod =1e9+7;const int maxn=2e5+5;int prime[maxn];int cnt;int U[maxn];bitset<maxn> vis;int n;int a[maxn],t[maxn];int mx,mi;void pre_mobius(int m){    cnt=0;    U[1]=1;    vis.reset();    for(int i=2; i<m; ++i){        if(!vis[i]){            U[i]=-1;            prime[cnt++]=i;        }        int cur;        for(int j=0; j<cnt&&(cur=i*prime[j])<m; ++j){            vis[cur]=1;            if(i%prime[j]){                U[cur]=-U[i];            }            else{                U[cur]=0;                break;            }        }    }}LL qpow(LL a,LL b){    LL re=1;    for(;b;a=(a*a)%mod,b>>=1)        if(b&1)re=re*a%mod;    return re;}int main(){    pre_mobius(maxn);    int T;    int kase=0;    scanf("%d",&T);    while(T--){        mx=-1,mi=0x3f3f3f3f;        memset(t,0,sizeof(t));        scanf("%d",&n);        for(int i=1;i<=n;++i){            scanf("%d",a+i);            t[a[i]]++;            mx=max(mx,a[i]);            mi=min(mi,a[i]);        }        for(int i=mx;i>0;--i){            t[i]=t[i]+t[i+1];        }        LL ans=0;        for(int i=2;i<=mi;++i){            LL add=-U[i];            if(!add)continue;            LL r=i,amt=1;            while(r<=mx){                add=add*qpow(amt,t[r]-t[r+i])%mod;                r+=i;                amt++;            }            ans=(ans+add+mod)%mod;        }        printf("Case #%d: %lld\n",++kase,ans);    }}
原创粉丝点击