CF1842G Tenzing and Random Operations 题解 / 组合意义保平安

题目传送门:CF1842G Tenzing and Random Operations

考虑将 \(\prod a_i\),转化成组合意义。

有一个数一开始为 \(1\),然后依次经过 \(1\)\(n\),然后每次乘以 \(a_i\)

然后随机修改,相当于在 \(i\) 放了一个备选项,不乘 \(a_i\) 而乘 \(v\)

然后我们发现,我们最多只有 \(n\) 个位置是乘 \(v\),考虑将这个设进状态。

\(f_{i,j}\) 表示,前 \(i\) 个位置,且已经选择了 \(j\)\(v\)

转移就是三种情况,使用 \(a_i\),用之前选过的 \(v\),新选择一个 \(v\)

  1. \(f_{i,j} = f_{i-1,j} \times a_i\)
  2. \(f_{i,j} = f_{i-1,j} \times j \times v\)
  3. \(f_{i,j} = f_{i-1,j-1} \times i \times (m-j+1) \times v\)

初始 \(f_{0,0}=1\),答案即为 \(\sum \frac{f_{n,i}\times n^{m-i} }{n^m} = \sum f_{n,i} \times n^{-i}\)

#include<bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
const int N=5010,mod=1e9+7; 
inline int read(){
	char c=getchar();
	int f=1,ans=0;
	while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
	while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
	return ans*f;
}
int n,m,v,a[N],f[N][N];
void exgcd(int a,int b,int &x,int &y){
	if (b==0) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}
inline int inv(int a){
	int x,y;
	exgcd(a,mod,x,y);
	return (x%mod+mod)%mod;
}
main(){
	n=read(),m=read(),v=read();
	for (int i=1;i<=n;i++) a[i]=read();
	f[0][0]=1;
	for (int i=1;i<=n;i++)
		for (int j=0;j<=min(n,m);j++){
			f[i][j]=(f[i][j]+f[i-1][j]*a[i]%mod)%mod;
			f[i][j]=(f[i][j]+f[i-1][j]*j%mod*v%mod)%mod;
			if (j) f[i][j]=(f[i][j]+f[i-1][j-1]*i%mod*(m-j+1)%mod*v%mod)%mod;
		}
	int ans=0,sum=1;
	for (int i=0;i<=min(n,m);i++) ans=(ans+f[n][i]*sum%mod)%mod,sum=sum*inv(n)%mod;
	cout <<ans;
    return 0;
}
posted @ 2026-01-08 21:57  OTn53_qwq  阅读(26)  评论(0)    收藏  举报