F - Strivore abc 171 (困难组合数)

F - Strivore

Face


题意

  • 给定一个数 k k k, 一个串 s s s
  • 求在串 s s s中插入任意 k k k个小写字符后能组成多少种新串

数据范围: 1 ≤ n ≤ 1 0 6 , 1 ≤ s . s i z e ( ) ≤ 1 0 6 1\leq n\leq 10^6, 1\leq s.size() \leq 10^6 1n106,1s.size()106


前置技能

  • 聪明的脑瓜?
  • 组合数

Tutorial:

  • 去重策略 (似乎是套路)

r e s = ∑ i = 0 k 2 6 i × 2 5 k − i × C k + l e n − i − 1 l e n − 1 res = \sum_{i = 0}^{k}26^i\times25^{k-i}\times C_{k+len-i-1}^{len - 1} res=i=0k26i×25ki×Ck+leni1len1

复杂度: O ( k × l o g ( 玄 学 ) ) O(k\times log(玄学)) O(k×log())


code:



#include
using namespace std;
#define _rep(n, a, b) for (int n = (a); n <= (b); ++n)
#define _rev(n, a, b) for (int n = (a); n >= (b); --n)
#define _for(n, a, b) for (int n = (a); n < (b); ++n)
#define _rof(n, a, b) for (int n = (a); n > (b); --n)
#define oo 0x3f3f3f3f3f3f
#define ll long long
#define db double
#define eps 1e-3
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair
#define pdd pair
#define endl "\n"
const int mod = 1e9 + 7;
const int maxn = 2e6 + 10;
vector<ll> f(maxn), invf(maxn);

ll qpow(ll a, ll b) {
    ll ret = 1;
    for (; b; a = a * a % mod, b >>= 1) {
        if (b & 1) {
            ret = ret * a % mod;
        }
    }
    return ret;
}

void prework(){
    f[0] = 1;
    _rep(i, 1, maxn-1){
        f[i] = f[i-1] * i%mod;
    }
    invf[maxn - 1] = qpow(f[maxn - 1], mod - 2);
    for(int i = maxn-2;i>=0;i--){
        invf[i] = invf[i + 1] * (i + 1) % mod;
    }

}

ll C(ll n, ll m){
    if(n>m||m<0)return 0;
    if(n==0||m==n) return 1;
    ll res = (f[m] * invf[m-n]%mod *invf[n])%mod;
    return res;
}
signed main() {
    int k;
    string s;
    cin >> k >> s;
    prework();
    ll len = s.size();
    ll res = 0;
    _rep(i, 0, k) {
        res = (res + qpow(26, i) * qpow(25, k - i)%mod  * C(len-1, k + len - 1 - i)%mod)%mod;
    }
    cout << res << endl;
}

牛客网有个类似的 可以练练手

#include
using namespace std;
#define _rep(n, a, b) for (int n = (a); n <= (b); ++n)
#define _rev(n, a, b) for (int n = (a); n >= (b); --n)
#define _for(n, a, b) for (int n = (a); n < (b); ++n)
#define _rof(n, a, b) for (int n = (a); n > (b); --n)
#define oo 0x3f3f3f3f3f3f
#define ll long long
#define db double
#define eps 1e-3
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair
#define pdd pair
#define endl "\n"
const int mod = 1e9 + 7;
const int maxn = 2e6 + 10;
vector<ll> f(maxn), invf(maxn);

ll qpow(ll a, ll b) {
    ll ret = 1;
    for (; b; a = a * a % mod, b >>= 1) {
        if (b & 1) {
            ret = ret * a % mod;
        }
    }
    return ret;
}

void prework(){
    f[0] = 1;
    _rep(i, 1, maxn-1){
        f[i] = f[i-1] * i%mod;
    }
    invf[maxn - 1] = qpow(f[maxn - 1], mod - 2);
    for(int i = maxn-2;i>=0;i--){
        invf[i] = invf[i + 1] * (i + 1) % mod;
    }

}

ll C(ll n, ll m){
    if(n>m||m<0)return 0;
    if(n==0||m==n) return 1;
    ll res = (f[m] * invf[m-n]%mod *invf[n])%mod;
    return res;
}
signed main() {
    int k;
    string s;
    cin >> s >> k;
    prework();
    ll len = s.size();
    ll res = 0;

    _rep(i, 0, k - len) {
        res = (res + qpow(26, i) * qpow(25, k - i - len)%mod  * C(len-1, k  - 1 - i)%mod)%mod;
    }
    cout << res << endl;

}

你可能感兴趣的:(好题,数学,排列组合)