HDU4675 莫比乌斯反演

卡了半天原来是卡在预处理上了

以为n根号n的预处理不碍大事

后来发现可以用nlog来处理

当时没想到。。

其实原理很简单。。。

看了一眼别人的代码

其他的都是自己推的

一道简单的组合数加中档莫比乌斯的题

其实莫比乌斯的本质就是容斥

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5,M=1e9+7;
ll U[N+10],V[N+10],A[N+10],B[N+10],n,m,k,JC[N+10],INV[N+10],FF[N+10];
ll C(ll a,ll b,ll m){
    return JC[a]*INV[b]%m*INV[a-b]%m;
}
ll quickmod(ll a,ll b,ll m){
    ll ans=1;
    for(;b;b>>=1){
        if(b&1)ans=ans*a%m;
        a=a*a%m;
    }
    return ans;
}
ll F(ll x){
	if(B[x]<n-k)return 0;
    return C(B[x],n-k,M)*quickmod(m/x,n-B[x],M)%M*quickmod(m/x-1,B[x]-n+k,M)%M;
}
inline void read(ll &x){
	char ch;bool ok;
    for(ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') ok=1;
    for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    if(ok) x=-x;
}
int main(){
	//freopen("D://abc.txt","r",stdin);
    //freopen("D://1.txt","w",stdout);
    JC[0]=1,INV[0]=1;
    for(ll i=1;i<=N;++i)JC[i]=JC[i-1]*i%M,INV[i]=quickmod(JC[i],M-2,M);
    for(int i=1;i<=N;++i)U[i]=1;
    for(int i=2;i<=N;++i){
        if(V[i])continue;
        for(int j=i;j<=N;j+=i){
            V[j]=1;
            if(j%(i*i)==0)U[j]=0;
            else U[j]*=-1;
        }
    }
    while(cin>>n>>m>>k){
    	memset(B,0,sizeof B);
	    for(int i=1;i<=n;++i){
	        read(A[i]);
	        ++B[A[i]];
	    }
	    for(int i=1;i<=m;++i){
	    	for(int j=i*2;j<=m;j+=i){
	    		B[i]+=B[j];
			}
		}
	    for(int i=1;i<=m;++i)FF[i]=F(i);
	    for(int i=1;i<=m;++i){
	        ll ans=0;
	        for(int j=i;j<=m;j+=i){
	            ans=(ans+(U[j/i]*FF[j])%M+M)%M;
	        }
	    	printf("%lld",ans);
	    	if(i!=m)printf(" ");
	    	else printf("\n");
	    }
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值