0x37 容斥原理与莫比乌斯函数
多重集的组合数公式得记下。cf451E就是这个的裸题
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; int n;LL m; LL quick_pow(LL A,LL p) { LL ret=1; while(p!=0) { if(p%2==1)ret=(ret*A)%mod; A=(A*A)%mod;p/=2; } return ret; } LL jiecheng(LL k) { LL ret=1; for(int i=1;i<=k;i++)ret=(ret*i)%mod; return ret; } LL a[30]; LL calc(int zt) { LL u=n+m-1,cnt=0; for(int i=0;i<n;i++) if(zt&(1<<i)) u-=a[i], cnt++; u-=cnt; if(u<n-1)return 0; LL ret=1; for(int i=1;i<=n-1;i++) { ret=(ret*(u%mod))%mod, u--; } return (cnt%2==0)?ret:-ret; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%d%lld",&n,&m); for(int i=0;i<n;i++)scanf("%lld",&a[i]); int li=(1<<n)-1; LL ans=0,ny=quick_pow(jiecheng(n-1),mod-2); for(int zt=0;zt<=li;zt++) { ans=(ans+calc(zt)*ny%mod)%mod; } printf("%lld\n",(ans+mod)%mod); return 0; }
bzoj1101 没什么难度。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; bool v[51000]; int pr,prime[51000],u[51000]; void mobius_inversion() { u[1]=1;pr=0; memset(v,true,sizeof(v)); for(int i=2;i<=50010;i++) { if(v[i]==true) { prime[++pr]=i; u[i]=-1; } for(int j=1;j<=pr&&i*prime[j]<=50010;j++) { v[i*prime[j]]=false; if(i%prime[j]==0) { u[i*prime[j]]=0; break; } else u[i*prime[j]]=-u[i]; } u[i]+=u[i-1]; } } int solve(int n,int m) { int li=min(n,m),last,ans=0; for(int i=1;i<=li;i=last+1) { last=min(n/(n/i),m/(m/i)); ans+=(u[last]-u[i-1])*(n/i)*(m/i); } return ans; } int main() { mobius_inversion(); int T; scanf("%d",&T); while(T--) { int a,b,d; scanf("%d%d%d",&a,&b,&d); if(d==0){printf("0\n");continue;} a/=d;b/=d; printf("%d\n",solve(a,b)); } return 0; }
pain and happy in the cruel world.