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\)。
- \(f_{i,j} = f_{i-1,j} \times a_i\)
- \(f_{i,j} = f_{i-1,j} \times j \times v\)
- \(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;
}

浙公网安备 33010602011771号