hdu-6053TrickGCD

来源:互联网 发布:新浪微博推广淘宝产品 编辑:程序博客网 时间:2024/05/20 05:22

    莫比乌斯的函数的一个应用,补题的时候怒补了一波莫比乌斯。但是到现在还是一知半解的,这题大致就是要算每一个数的倍数的个数,但是如果枚举每一个Ai的话铁定还会超时,那么就要想到优化,cnt数组就是这样的一个优化,cnt[i]就是小于等于i数的个数,相当于前缀和,然后再用莫比乌斯的u函数容斥,这里保存一下在别人博客看到的莫比乌斯函数的几个形式。。方便以后查看。

详情点击:点击打开链接

  

定理:是定义在非负整数集合上的两个函数,并且满足条件,那么我们得到结论

 

     

 

在上面的公式中有一个函数,它的定义如下:

    (1)若,那么

    (2)若均为互异素数,那么

    (3)其它情况下

对于函数,它有如下的常见性质:

    (1)对任意正整数

                           

        (2)对任意正整数

        

#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>#define siz 100005#define LL long longusing namespace std;int gp[siz];int n;int mu[siz];const LL mod=1e9+7;int maxx,cnt[siz*2];LL quck_mod(LL x,LL y){    LL ret=1;    while(y>0){        if(y&1) ret=ret*x%mod;        x=x*x%mod;        y>>=1;    }    return ret;}void _u(){    mu[1]=1;    for(int i=1;i<siz;i++){        for(int j=i+i;j<siz;j+=i){            mu[j]-=mu[i];;        }    }}void solve(){    LL ans=0;    for(int i=2;i<=maxx;i++){        LL temp=1;        for(int j=1;i*j<=100000;j++){            temp=(temp*quck_mod((LL)j,cnt[i*j+i-1]-cnt[i*j-1]))%mod;           // cout<<temp<<endl;        }        ans=(ans-temp*mu[i]+mod)%mod;    }    printf("%I64d\n",ans);}int main(){    _u();    int t;    scanf("%d",&t);    for(int i=1;i<=t;i++){        scanf("%d",&n);        maxx=100000;        for(int j=1;j<2*siz;j++){            cnt[j]=0;        }        for(int j=1;j<=n;j++){            scanf("%d",&gp[j]);            cnt[gp[j]]++;            maxx=min(maxx,gp[j]);        }        for(int j=1;j<2*siz;j++) cnt[j]+=cnt[j-1];        printf("Case #%d: ",i);        solve();    }    return 0;}



原创粉丝点击