HDU6053TrickGCD(莫比乌斯函数)

来源:互联网 发布:淘宝站外推广怎么做 编辑:程序博客网 时间:2024/05/20 05:25
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;/*给定数列A,求解数列B有多少种数列B满足 1<=Bi<=Ai,且对于任意区间[l,r],gcd(Bl,Bl+1,...Br)>=2*/typedef long long LL;const int maxn=1e5+5;const int mod=1e9+7;bool check[maxn];int prime[maxn];int mu[maxn];//莫比乌斯函数void Moblus(){    memset(check,false,sizeof(check));    mu[1]=1;    int tot=0;    for(int i=2;i<=maxn;i++)    {        if(!check[i])        {            prime[tot++]=i;            mu[i]=-1;        }        for(int j=0;j<tot;j++)        {            if(i*prime[j]>maxn) break;            check[i*prime[j]]=true;            if(i%prime[j]==0)            {                mu[i*prime[j]]=0;                break;            }            else            {                mu[i*prime[j]]= -mu[i];            }        }    }}//快速幂LL pow_mod(LL a, LL n){    LL  ret=1;    LL tmp=a%mod;    while(n)    {        if(n&1) ret=ret*tmp%mod;        tmp=tmp*tmp%mod;        n>>=1;    }    return ret;}int n;int sum[maxn];int main(){    Moblus();    int T;    scanf("%d",&T);    int kase=1;    while(T--)    {        scanf("%d",&n);        int x;        int mx=0;        memset(sum,0,sizeof(sum));        for(int i=0;i<n;i++)        {            scanf("%d",&x);            sum[x]++;            mx=max(mx,x);        }        for(int i=1;i<=mx;i++)        {            sum[i]=sum[i]+sum[i-1];            //printf("sum=%d\n",sum[i]);        }        LL ans=0;        for(int i=2;i<=mx;i++)        {            if(sum[i-1]>0)            {                break;            }            LL tmp=1;            for(int j=i;j<=mx;j+=i)            {                int k=sum[min(j+i-1,mx)]-sum[j-1];                tmp=tmp*pow_mod(j/i,k)%mod;            }            ans=(ans+tmp*mu[i]*-1)%mod;        }        printf("Case #%d: %lld\n",kase++,(ans%mod+mod)%mod);    }    return 0;}
原创粉丝点击