AtCoder Grand Contest 038

ABC 略

D. Unique Path

E. Gachapon

考虑 \(P(ans\leqslant n)=n![x^n]\prod(e^{A_ix}-\sum\limits_{j=0}^{B_i-1}\frac{(\frac {A_i}S)^jx^j}{j!})\),后面的内容也就顺理成章了。

我们的欲求式是 \(\sum\limits_{n=0} P(ans>n)=\sum\limits_{n=0} 1-P(ans\leqslant n)=\sum\limits_{n=0} 1-n![x^n]F(x)=-\sum\limits_{n=0} n![x^n](F(x)-e^x)\)

套路地,我们 \(dp\) 出它的系数,即 \(F(x)=\sum\limits_{i,j} dp_{i,j}e^{\frac iS}x^j\),则 \(\sum\limits_{n=0} n![x^n]F(x)=\sum\limits_{n=0} \sum\limits_{i,j} dp_{i,j}\dfrac{(\frac iS)^{n-j}n!}{(n-j)!}=\sum\limits_{i,j} dp_{i,j}j!\sum\limits_{n=0} \dbinom{n}{j} (\frac iS)^{n-j}\)

事实上 \(\sum\limits_{n=0}\dbinom{n}{a}b^{n-a}=(\frac 1{1-b})^{a+1}\),于是做完了。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=998244353;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
const int N=405;
int n,m,A[N],B[N],S,dp[N][N],F[N][N],tmp[N],ta,tb,ans;
int fac[N],inv[N],ifc[N];
inline int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1ll*res*x%mod;
		x=1ll*x*x%mod;y>>=1;
	}return res;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++)
		A[i]=read(),B[i]=read(),S+=A[i];
	fac[0]=inv[1]=ifc[0]=1;
	for(int i=2;i<N;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=1;i<N;i++)fac[i]=1ll*fac[i-1]*i%mod;
	for(int i=1;i<N;i++)ifc[i]=1ll*ifc[i-1]*inv[i]%mod;
	dp[0][0]=1;tmp[0]=mod-1;
	for(int i=1;i<=n;i++){
		int w=1ll*A[i]*inv[S]%mod;
		for(int j=1;j<B[i];j++)tmp[j]=1ll*tmp[j-1]*w%mod*inv[j]%mod;
		for(int a=ta;a>=0;a--)
			for(int j=tb;j>=0;j--)
				for(int k=0;k<B[i];k++)
					F[a][j+k]=(F[a][j+k]+1ll*dp[a][j]*tmp[k])%mod;
		ta+=A[i],tb+=B[i]-1;
		for(int a=ta;a>=A[i];a--)
			for(int j=tb;j>=0;j--)
				F[a][j]=(dp[a-A[i]][j]+F[a][j])%mod;
		for(int a=0;a<=ta;a++)
			for(int b=0;b<=tb;b++)
				dp[a][b]=F[a][b],F[a][b]=0;
	}
	for(int i=0;i<ta;i++){
		int K=1ll*i*inv[S]%mod,kk=ksm(1-K+mod,mod-2);
		for(int j=0;j<=tb;j++)
			ans=(ans+1ll*dp[i][j]*fac[j]%mod*ksm(kk,j+1))%mod;
	}printf("%d\n",mod-ans);
    return 0;
}

F. Two Permutations

易知一个置换环要么保留,要么全部还原。我们考虑 P 的置换环 \(a\) 和 Q 的置换环 \(b\) 的共同元素 \(i\)

  • \(P_i=Q_i=i\),则无论 \(a,b\) 选或不选,都是 \(1\) 的贡献

  • \(P_i=i,Q_i\neq i\),若 \(b\) 不选,则有 \(1\) 的贡献

  • \(P_i\neq i,Q_i=i\),若 \(a\) 不选,则有 \(1\) 的贡献

  • \(P_i=Q_i\neq i\),若 \(a,b\) 同时选或不选,都有 \(1\) 的贡献

  • \(P_i\neq i,Q_i\neq i,P_i\neq Q_i\),若 \(a,b\) 都不选,则有 \(1\) 的贡献

套路网络流即可。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
#define ll long long
const int maxn=1e6+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m,P[maxn],Q[maxn],idp[maxn],idq[maxn],cnt,ans,S,T;
int dep[maxn];queue<int>q;
int beg[maxn],nex[maxn],to[maxn],w[maxn],e=1;
#define pii pair<int,int>
#define mkp make_pair
map<pair<int,int>,int>mp;
inline void add(int x,int y,int z){
	if(mp[mkp(x,y)]){w[mp[mkp(x,y)]]+=z;return;}
	++e;nex[e]=beg[x];beg[x]=e;to[e]=y;w[e]=z;mp[mkp(x,y)]=e;
	++e;nex[e]=beg[y];beg[y]=e;to[e]=x;w[e]=0;
}
inline int bfs(){
	for(int i=1;i<=T;i++)dep[i]=0;
	dep[S]=1;q.push(S);
	while(!q.empty()){
		int x=q.front();q.pop();
		for(int i=beg[x];i;i=nex[i]){
			int t=to[i];
			if(w[i]&&!dep[t]){
				dep[t]=dep[x]+1;
				q.push(t);
			}
		}
	}return dep[T];
}
inline int dfs(int x,int lim){
	if(x==T||!lim)return lim;
	int res=0;
	for(int i=beg[x];i&&lim;i=nex[i]){
		int t=to[i];
		if(w[i]&&dep[t]==dep[x]+1){
			int f=dfs(t,min(lim,w[i]));
			if(!f){dep[t]=0;continue;}
			w[i]-=f;w[i^1]+=f;
			res+=f;lim-=f;
		}
	}return res;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++)P[i]=read()+1;
	for(int i=1;i<=n;i++)Q[i]=read()+1;
	for(int i=1,x;i<=n;i++)if(!idp[i]){++cnt;x=i;while(!idp[x])idp[x]=cnt,x=P[x];}
	for(int i=1,x;i<=n;i++)if(!idq[i]){++cnt;x=i;while(!idq[x])idq[x]=cnt,x=Q[x];}
	S=++cnt,T=++cnt;
	for(int i=1;i<=n;i++){
		if(P[i]==i&&Q[i]==i){ans++;continue;}
		if(P[i]==Q[i]){add(idp[i],idq[i],1),add(idq[i],idp[i],1);continue;}
		if(P[i]==i){add(S,idq[i],1);continue;}
		if(Q[i]==i){add(idp[i],T,1);continue;}
		add(idp[i],idq[i],1);
	}
	while(bfs())ans+=dfs(S,inf);
	printf("%d\n",n-ans);
	return 0;
}
posted @ 2022-04-09 18:09  syzf2222  阅读(25)  评论(0编辑  收藏  举报