【DP】翻硬币(jzoj 3921)
翻硬幣
jzoj 3921
題目大意:
給你一個(gè)長(zhǎng)度為nnn的當(dāng)前01串和目標(biāo)01串,現(xiàn)在你要做mmm此操作,每次操作你要使kkk個(gè)不同的位取反,現(xiàn)在問你有多少種方法可以使當(dāng)前01串變?yōu)槟繕?biāo)01串
輸入樣例:
3 2 1 100 001輸出樣例:
2樣例解釋:
100?>101?>001100->101->001100?>101?>001
100?>000?>001100->000->001100?>000?>001
數(shù)據(jù)范圍
對(duì)于30% 的數(shù)據(jù),N<=4;,0<=K<=5N <=4;,0 <= K <= 5N<=4;,0<=K<=5
對(duì)于60% 的數(shù)據(jù),N<=10N <= 10N<=10
對(duì)于100% 的數(shù)據(jù),1<=N<=100;,0<=K<=100,0<=M<=N1 <= N <= 100;,0 <= K <= 100,0 <= M <= N1<=N<=100;,0<=K<=100,0<=M<=N
解題思路:
我們?cè)O(shè)fi,jf_{i,j}fi,j?為第iii次操作,與目標(biāo)操作有jjj位不同的種數(shù)
當(dāng)j?kj\geqslant kj?k時(shí)(j<kj<kj<k的情況見代碼)
我們從fi?1,jf_{i-1,j}fi?1,j?轉(zhuǎn)移到fi,kf_{i,k}fi,k?首先一定要取反j?kj-kj?k次
多余的m?(j?k)m-(j-k)m?(j?k)平分成與結(jié)果相同的和不同的來(lái)取反
這樣我們就得出了狀態(tài)轉(zhuǎn)移方程:
ft,j=ft,j+ft?1,i?Cim?(j?k)2?Cn?ij?i+(m?(j?k)2)(j?k)f_{t,j}=f_{t,j}+f_{t-1,i} * C_i^{\frac{m - (j - k)}{2}}* C_{n - i}^{j - i + (\frac{m - (j - k)}{2})}\ \ \ \ \ \ (j \geqslant k)ft,j?=ft,j?+ft?1,i??Ci2m?(j?k)???Cn?ij?i+(2m?(j?k)?)???????(j?k)
注:代碼中的變量有所不同
代碼:
5
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define abs(x) (x) < 0? -(x) : (x) #define ll long long #define wyc 1000000007//%%% using namespace st d; ll n, m, k, s, C[150][150], f[150][150]; string str, str1; int main() {for (int i = 0; i <= 100; ++i)C[i][0] = 1;for (int i = 1; i <= 100; ++i)for (int j = 1; j <= 100; ++j)C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % wyc;//求組合數(shù)scanf("%lld%lld%lld", &n, &k, &m);cin>>str;cin>>str1;for (int i = 0; i < n; ++i)s += (str[i] != str1[i]);if (s&1 && !(m&1))//偶數(shù)無(wú)法拼成基數(shù){printf("0");return 0;}f[0][s] = 1;for (ll t = 1; t <= k; ++t)for (ll i = 0; i <= n; ++i)for (ll j = max((i + m) & 1, i - m); j <= min(n, i + m); j += 2)//一些小優(yōu)化if ((i + j + 1)&1 && abs(i - j) <= m)//也是一些小優(yōu)化{if (j >= i)f[t][j] = (f[t][j] + f[t - 1][i] * C[i][((m - (j - i)) >> 1)] % wyc * C[n - i][j - i + ((m - (j - i)) >> 1)] % wyc) % wyc;//狀態(tài)轉(zhuǎn)移else f[t][j] = (f[t][j] + f[t - 1][i] * C[i][i - j + ((m - (i - j)) >> 1)] % wyc * C[n - i][((m - (i - j)) >> 1)] % wyc) % wyc;//反過(guò)來(lái)}printf("%lld", f[k][0]);return 0; }總結(jié)
以上是生活随笔為你收集整理的【DP】翻硬币(jzoj 3921)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星S23 FE国行版正式开售!8GB+
- 下一篇: 【单调栈】奶牛的歌声(jzoj 1256