日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ABC 171 F - Strivore 【容斥】

發布時間:2023/10/11 编程问答 64 如意码农
生活随笔 收集整理的這篇文章主要介紹了 ABC 171 F - Strivore 【容斥】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

https://atcoder.jp/contests/abc171/tasks/abc171_f

題意

給你一個數 \(k\) ,一個字符串 \(s\) (只包含小寫字母)

定義一次操作:把任意小寫英文字母填入當前串的任意位置。問做完 \(k\) 次操作能得到多少不同的字符串?

思路

首先試著直接求出答案,那么就是往當前串的空隙里插入字符。

原字符串的空隙一共有 \(|S|\) 個。對于字符串原有的字符 \(s_i\) 來說,它會把它之后第一次出現的和 \(s_{i+1}\) 相同的字符當成 \(s_{i+1}\),所以除了最后一個空隙可以任意填(26種),原字符串的空隙可以填入的字符都是25種。

我的意思是 \(\sum_{i=0} ^ {k} 26^i * 25^{k - i} * C_{k - i + |S| - 1} ^ {|S| - 1}\) 。

然而可以證偽。

因為我的做法是對于同一個 \(i\),把所有的排列組合方案數和 \(25^{k - i}\) 相乘,可能會多算,例如 _a_b , 填入了aa,填在a之后就都可以,有填的a落在a之前就不可以 。

正解:

正難則反。

ans = \(26^{k + |S|}\) - 不包含 \(S\) 這個子序列的字符串方案數

check是否包含 \(S\) 這個子序列的方法:從字符串的第一個開始找,找到和 \(s_i\) 相同的字符串后,\(i\) += 1

新字符串可以包含 \(S\) 這個子序列的一個前綴 from 0 to |S| - 1

字符串的空隙間可以填入25種字符,由于不包含完整的 \(S\),字符串的末尾的空隙也只能填入25種字符

ans = \(26^{k + |S|} - \sum_{i = 0} ^ {|S| - 1} 25^{k + |S| - i} * C_{k + |S|} ^ {i}\)

code

思路清楚了,代碼實現就比較簡單了。

ll qpow(ll a, ll x) {
ll ans = 1;
while(x) {
if(x & 1) {ans *= a; ans %= mod;}
a *= a; a %= mod; x /= 2;
}
return ans;
} void init(int n) {
fac[0] = 1;
for(int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i % mod;
}
inv[n] = qpow(fac[n], mod - 2);
for(int i = n - 1; i >= 1; i--) {
inv[i] = inv[i + 1] * (i + 1) % mod;
}
inv[0] = 1;
} ll C(int n, int m) {
if(n < m) return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
} int main () {
init(2e6);
scanf("%d%s", &k, s + 1);
n = strlen(s + 1);
ll ans = qpow(26, n + k);
for (int i = 0; i < n; i++) {
ans = (ans - qpow(25, n + k - i) * C(n + k, i) % mod + mod) % mod;
}
printf("%lld\n", ans);
return 0;
}

總結

以上是生活随笔為你收集整理的ABC 171 F - Strivore 【容斥】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。