hdu 6053-莫比乌斯反演

来源:互联网 发布:圆方软件论坛 编辑:程序博客网 时间:2024/05/27 10:44

题目链接:点击打开链接


题解思路:应用莫比乌斯就是处理容斥,这里用原始的容斥肯定超时。


代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;typedef long long ll;int n,m;const int mx = 1e5+10,mod = 1e9+7;int mu[mx],pri[mx],num[mx],sum[mx<<1];bool vis[mx];void init(){    int top = 0;    for(int i=2;i<mx;i++){        if(!vis[i]){            pri[top++] = i;            mu[i] = -1;        }        for(int j=0;j<top&&pri[j]*i<mx;j++){            int val = i*pri[j];            vis[val] = 1;            if(i%pri[j]==0){                mu[val] = 0;                break;            }            mu[val] = -mu[i];        }    }}ll kuaisu(ll x,ll y){    ll ans = 1;    while(y){        if(1&y) ans = ans*x%mod;        y >>= 1;        x = x*x%mod;    }    return ans;}int main(){    int t,cas = 1;    scanf("%d",&t);    init();    while(t--){        memset(sum,0,sizeof(sum));        scanf("%d",&n);        int minn = 1e9,maxx = 0;        for(int i=1;i<=n;i++){            scanf("%d",num+i);            minn = min(minn,num[i]);            maxx = max(maxx,num[i]);            sum[num[i]]++;        }        for(int i=mx-2;i>=0;i--) sum[i] += sum[i+1]; //大等i的有几个        ll ans =0;        for(int i=2;i<=minn;i++){            ll cnt = 1,ret = -mu[i];            int p = i;            while(p<=maxx)            ret = (ret*kuaisu(cnt,sum[p]-sum[p+i]))%mod, p += i,cnt++;            ans = (ans+ret+mod)%mod;        }        printf("Case #%d: %I64d\n",cas++,ans);    }    return 0;}

也可以用递归形式的容斥可行


代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;typedef long long ll;int n,m,minn,maxx;const int mx = 1e5+10,mod = 1e9+7;int pri[mx],num[mx],sum[mx<<1];bool vis[mx];void init(){    int top = 0;    for(int i=2;i<mx;i++){        if(!vis[i]) pri[top++] = i;        for(int j=0;j<top&&pri[j]*i<mx;j++){            vis[i*pri[j]] = 1;            if(i%pri[j]==0) break;        }    }}ll kuaisu(ll x,ll y){    ll ans = 1;    while(y){        if(1&y) ans = ans*x%mod;        y >>= 1;        x = x*x%mod;    }    return ans;}ll dfs(int cnt,int pos,ll val){    ll ans = 0;    for(int i = pos+1;val*pri[i]<=minn;i++){        ll s = val*pri[i],ret = 1;        int p = s,c = 1;        while(p<=maxx) ret = (ret*kuaisu(c++,sum[p]-sum[p+s]))%mod, p += s;        if(cnt&1) ans = (ans+ret)%mod;        else ans = (ans-ret+mod)%mod;        ans = (ans+dfs(cnt+1,i,s))%mod;    }    return ans;}int main(){    int t,cas = 1;    scanf("%d",&t);    init();    while(t--){        memset(sum,0,sizeof(sum));        scanf("%d",&n);        minn = 1e9,maxx = 0;        for(int i=1;i<=n;i++){            scanf("%d",num+i);            minn = min(minn,num[i]);            maxx = max(maxx,num[i]);            sum[num[i]]++;        }        for(int i=mx-2;i>=0;i--) sum[i] += sum[i+1]; //大等i的有几个        printf("Case #%d: %lld\n",cas++,dfs(1,-1,1));    }    return 0;}

原创粉丝点击