zoukankan      html  css  js  c++  java
  • UOJ #390. 【UNR #3】百鸽笼

    UOJ #390. 【UNR #3】百鸽笼

    题目链接

    看这道题之前先看一道相似的题目 【PKUWC2018】猎人杀

    考虑类似的容斥:

    我们不妨设处理(1)的概率。

    我们令集合(T)中的所有鸽笼都在(1)变空之前不为空的,其它的鸽笼随便。要做到这一点,我们只需要令每个(T)集合中的鸽笼容量(--)就行了。然后我们用背包背出所有序列的方案数(不包括(1)),然后在将(1)插入序列中。插入时,将(w_i-1)个随便插入,然后再将一个放在序列末尾。

    具体实现时,我们可以枚举"(1)",然后对其它的鸽笼进行背包。但是复杂度会达到(O(n^6))。于是我们先对所有鸽笼进行背包,计算"(1)"的时候直接将它的贡献消除,也就是做"反背包"。复杂度就是(O(n^5))

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 35
    #define mod 998244353
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    int n,w[N];
    ll ksm(ll t,ll x) {
    	ll ans=1;
    	for(;x;x>>=1,t=t*t%mod)
    		if(x&1) ans=ans*t%mod;
    	return ans;
    }
    
    ll fac[1005],inv[1005];
    ll C(int n,int m) {
    	if(n<m) return 0;
    	return fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    
    ll f[N][N*N];
    ll g[N][N*N];
    int sum;
    
    void solve(int now) {
    	memcpy(f,g,sizeof(f));
    	for(int i=1;i<=n;i++) {
    		for(int j=0;j<=sum;j++) {
    			for(int q=0;q<w[now]&&q<=j;q++) {
    				f[i][j]=(f[i][j]-f[i-1][j-q]*C(j,q)%mod+mod)%mod;
    			}
    		}
    	}
    	ll ans=0,flag=1;
    	for(int i=0;i<n;i++,flag*=-1) {
    		ll invi=ksm(i+1,mod-2),t=ksm(invi,w[now]);
    		for(int j=0;j<=sum;j++,t=t*invi%mod) {
    			if(!f[i][j]) continue ;
    			(ans+=flag*C(j+w[now]-1,w[now]-1)*f[i][j]%mod*t%mod)%=mod;
    		}
    	}
    	cout<<(ans+mod)%mod<<" ";
    }
    
    int main() {
    	fac[0]=1;
    	for(int i=1;i<=900;i++) fac[i]=fac[i-1]*i%mod;
    	inv[900]=ksm(fac[900],mod-2);
    	for(int i=899;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
    	n=Get();
    	for(int i=1;i<=n;i++) w[i]=Get();
    	g[0][0]=1;
    	for(int i=1;i<=n;i++) {
    		sum+=w[i]-1;
    		for(int j=i;j>=1;j--) {
    			for(int k=sum;k>=0;k--) {
    				for(int q=0;q<w[i]&&q<=k;q++) {
    					(g[j][k]+=g[j-1][k-q]*C(k,q))%=mod;
    				}
    			}
    		}
    	}
    	for(int i=1;i<=n;i++) solve(i);
    	return 0;
    }
    
    
  • 相关阅读:
    python汉诺塔
    圆周率计算
    PIL: 建立一个GIF图
    Jieba库使用和好玩的词云
    Turtle库的建立——汉诺塔
    计算pi的精度+进度条显示
    Python——我所学习的turtle函数库
    Python——教你画朵太阳花
    Python常用模块re的使用
    正则表达式字符组/元字符/量词
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10159901.html
Copyright © 2011-2022 走看看