、

CF1842G Tenzing and Random Operations

题意

给定一个 \(n\) 和 \(a_i\) 和 \(v\)。有 \(m\) 次操作,每次等概率选择 \(i\in [1,n]\),将 \(\forall j\in [i,n],a_j\leftarrow a_j+v\),求操作结束后 \(\prod a_i\) 期望。

\(n\leq 5000\),\(m,v,a_i\leq 10^9\)

做法

考虑组合意义,\(\prod a_i\) 相当于一个人从 \(i\) 走向 \(i+1\) 有 \(v\) 种方案。那么加法操作就相当于我们可以在 \(p\) 后每次多有 \(v\) 条方案可以走。那么我们考虑动态规划,设 \(f_{i,j}\) 表示前 \(i\) 个位置,已经用了 \(j\) 个操作的方案数。那么有转移:

\[f_{i,j}a_{i+1}\rightarrow f_{i+1,j} \]

表示不用操作,

\[f_{i,j}jv\rightarrow f_{i+1,j} \]

表示用原来的操作,

\[f_{i,j}(i+1)(m-j)v\rightarrow f_{i,j+1 } \]

表示从旧的位置选择一个位置,填入 \(m-j\) 即一个还没有使用过的工具,那么答案就是:

\[\frac{\sum f_{n,i}n^{m-i}}{n^m} \]

即表示剩下的 \(m-i\) 个操作不重要可以在 \(n\) 个位置中随便填。复杂度 \(O(n\cdot\min(n,m))\)。

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
typedef long long ll;
const int MAXN=5005;
const int MOD=1e9+7;
int ksm(int a,int b){
    int ans=1;
    while(b){
        if(b&1){
            ans=1ll*ans*a%MOD;
        }
        a=1ll*a*a%MOD;
        b>>=1;
    }
    return ans;
}
int n,m,v,a[MAXN],f[MAXN][MAXN];
#define add(x,y) (((x)+=(y))>=MOD&&((x)-=MOD));
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>v;
    rep(i,1,n){
        cin>>a[i];
    }
    f[0][0]=1;
    rep(i,0,n-1){
        rep(j,0,min(m,i)){
            add(f[i+1][j],1ll*f[i][j]*a[i+1]%MOD);
            add(f[i+1][j],1ll*f[i][j]*j%MOD*v%MOD);
            add(f[i+1][j+1],1ll*f[i][j]*(i+1)%MOD*(m-j)%MOD*v%MOD);
        }
    }
    int ans=0;
    rep(i,0,min(n,m)){
        add(ans,1ll*f[n][i]*ksm(n,m-i)%MOD);
    }
    ans=1ll*ans*ksm(ksm(n,m),MOD-2)%MOD;
    cout<<ans<<"\n";
    return 0;
}
posted @ 2026-09-24 14:42  tanghg  阅读(7)  评论(0)    收藏  举报