AtCoder Beginner Contest 171 F 另类题解

ABC171F链接

可以发现一个字符串 \(T\) 能被 \(S\) 形成,当且仅当 \(len_T = len_S + k\) 且 \(S\) 是 \(T\) 的子序列。

考虑暴力 \(dp\) :\(dp_{i,j}\) 表示考虑到第 \(i\) 位,已经有 \(j\) 位匹配了 \(S\) 的方案数。

设 \(S\) 的长度为 \(m\) ,则:

\[ dp_{i,j}=\left\{ \begin{array}{rcl} dp_{i-1,j-1} + 25dp_{i-1,j} & & {j < m}\\ dp_{i-1,j-1} + 26dp_{i-1,j} & & {j = m}\\ \end{array} \right. \]

打个表,可以发现:

\[dp_{i,j} = C_i^j \times 25^{i-j} (j < m) \]

考虑用这样的方法,算出所有 \(dp_{i,m-1}\) 的值,然后用它们推出所有 \(dp_{i,m}\) 的值。

\(O(n + m)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mit map<int,int>::iterator
#define sit set<int>::iterator
#define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
#define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
#define ltype int
#define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
#define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
#define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
#define pii pair<int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back
#define fastio ios::sync_with_stdio(false)
const int inf=0x3f3f3f3f,mod=1000000007;
const double pi=3.1415926535897932,eps=1e-6;
void chmax(int &x,int y){if(x < y) x = y;}
void chmin(int &x,int y){if(x > y) x = y;}
int n,m,f[2000005],g[2000005],fac[2000005],inv[2000005];
char s[2000005];
int qpow(int x,int y){
    int res = 1;
    while(y) {
        if(y & 1) res = (ll)res * x % mod;
        x = (ll)x * x % mod;
        y >>= 1;
    }
    return res;
}
int C(int x,int y) {
    return (ll)fac[x] * inv[y] % mod * inv[x - y] % mod;
}
int main()
{
    scanf("%d",&n);
    scanf("%s",s);
    m = strlen(s);
    fac[0] = 1;
    rep(i,1,n+m) fac[i] = (ll)fac[i-1] * i % mod;
    inv[n + m] = qpow(fac[n + m], mod - 2);
    per(i,n+m-1,0) {
        inv[i] = (ll)inv[i + 1] * (i + 1) % mod;
    }

    //dp[0][0] = 1;
    /*rep(i,1,n + m) rep(j,0,min(i,m))  {
        if(j != m) {
            dp[i][j] = dp[i-1][j] * 25ll % mod;
            if(j) {dp[i][j] += dp[i-1][j-1];if(dp[i][j] >= mod) dp[i][j] -= mod;}
        }
        else {
            dp[i][j] = dp[i-1][j] * 26ll % mod;
            if(j) {dp[i][j] += dp[i-1][j-1];if(dp[i][j] >= mod) dp[i][j] -= mod;}
        }
    }
    printf("%d\n",dp[n+m][m]);*/
    rep(i,m-1,n+m) {
        f[i] = (ll)C(i, m - 1) * qpow(25, i - m + 1) % mod;
    }
    rep(i,m,n+m){
        g[i] = (g[i - 1] * 26ll % mod + f[i - 1]) % mod;
    }
    printf("%d\n",g[n + m]);
    return 0;
}
上一篇:「CF722E Research Rover」


下一篇:luogu 6046 纯粹容器 期望dp