Atcoder Beginner Contest 171 F

题意: 给定一个字符串 S S S,问插入 k k k个字符后可以形成多少个不同的字符串,答案对 1 0 9 + 7 10^9+7 109+7取模。
题解: 设字符串 S S S长度为 l e n len len,当插入了 k k k个字符后长度变为 l e n + k len+k len+k,故我们可以枚举字符串 S S S l e n len len个字符位置。

  1. 枚举 i i i为字符串 S S S S [ l e n − 1 ] S[len-1] S[len1]这个字符(最后一个字符)的位置,那么之后的 l e n + k − i len+k-i len+ki个字符每个都有 26 26 26个选择,即 2 6 l e n + k − i 26^{len+k-i} 26len+ki种。
  2. 那么对于前面 i − 1 i-1 i1个字符,(第 i i i个字符已经确定),我们先选择其中 l e n − 1 len-1 len1个位置作为 S S S的前 l e n − 1 len-1 len1个字符,则剩下的 i − l e n i-len ilen个则只有25种选择。至于这 i − l e n i-len ilen个只有25种就是如下图中 [ [ [^ S i ] {S_i}] Si]的这种字符,因为如果在 S i S_i Si S i − 1 S_{i-1} Si1间的 x x x这个位置出现了 S i S_i Si,那么相当于将这个 S i S_i Si的位置选择在了 x x x,后面的又是根据 S i + 1 S_{i+1} Si+1来选择了。
  3. 换种方式理解 2 2 2:这个过程可以看出 d p dp dp的状态转移。那么我们考虑 S S S中最后一个字符 S [ l e n − 1 ] S[len-1] S[len1]的位置,由 1 1 1可知道当确定了 S [ l e n − 1 ] S[len-1] S[len1]的位置后,其后面的所有字符有 26 26 26种选择,所以当我们在 S l e n − 2 S_{len-2} Slen2 S l e n − 1 S_{len-1} Slen1中插入了一个和 S l e n − 1 S_{len-1} Slen1相同的字符,相当于将 S l e n − 1 S_{len-1} Slen1的位置前移了,那么就是另一种情况了。所以枚举的前 i i i个字符中的 i − l e n i-len ilen个字符有 25 25 25种情况。

戳我进官方题解
下图是官方题解图:
官方题解图
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
ll fac[N], inv[N];
char s[N];
int k;

ll qp(ll a, ll b) {
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

void init() {
    fac[0] = fac[1] = 1;
    for(int i = 2; i < N; i++) fac[i] = fac[i - 1] * i % mod;
    inv[N - 1] = qp(fac[N - 1], mod - 2);
    for(int i = N - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
}

ll C(ll a, ll b) {
    if(b > a) return 0ll;
    return fac[a] * inv[b] % mod * inv[a - b] % mod;
}

ll add(ll a, ll b) {
    return (a + b) % mod;
}

int main()
{
    init();
    scanf("%d", &k);
    scanf("%s", s);

    ll res = 0;
    int len = strlen(s);

    for(int i = len; i <= k + len; i++) //枚举前i个字符为S的所在地,即第i个位置是字符s[len-1]的所在地
        res = add(res, C(i - 1, len - 1) * qp(25ll, i - len) % mod * qp(26ll, k + len - i) % mod);
    printf("%lld\n", res);

    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值