String Transmission

来源:互联网 发布:优惠券采集源码 编辑:程序博客网 时间:2024/06/07 04:42

Problem Statement

Bob has received a binary string of length N transmitted by Alice. He knows that due to errors in transmission, up to K bits might have been corrupted (and hence flipped). However, he also knows that the string Alice had intended to transmit was not periodic. A string is not periodic if it cannot be represented as a smaller string concatenated some number of times. For example, "0001", "0110" are not periodic while "00000", "010101" are periodic strings.

Now he wonders how many possible strings could Alice have transmitted.

 Input Format
The first line contains the number of test cases T. T test cases follow. Each case contains two integers N and K on the first line, and a binary string of length N on the next line.

Output Format
Output T lines, one for each test case. Since the answers can be really big, output the numbers modulo 1000000007.

Constraints
1T20
1N1000
0KN

Sample Input

3  5 0  00000  3 1  001  3 3  101

Sample Output

0  3  6
解题思路:一开始便想到思路,便是用总的修改方案数减去修改后使得字符串为周期串的方案数便是我们要求解的结果,因为总共能够修改N次,所以总的方案数为C(N,0)+C(N,1)+....+C(N,K),我们要求解的便是使其为周期串的方案数,很明显这个方案数是用DP去进行求解的,但是不会用DP去求解这个方案数啊,囧~~~~,所以只好想啊想,最终在瞄了一眼别人的代码后有了思路。首先要使得原串为周期串,则周期长度肯定为N的约数,我们便可以枚举这些约数,然后计算以这些约数为周期长度的方案数,假设周期串长度为i,则0,0+i,0+2*i...., 1,1+i,1+2*i... 等每一组的的字符必须要相等,要么为0要么为1,我们统计当周期长度为i时每一组中0的个数,则我们对于每一组有两种选择,第一种选择便是将所有的0变成1,需要消耗的修改的次数为0的个数,第二种便是将所有的1修改成0,需要消耗的修改次数为N/i减去该组中0的个数,这样对于N的每个约数,我们其实便是求i次操作,每次操作分为两种情况且总的修改的操作次数为K时的方案数,这个DP显然是很简单。最终要注意的问题,当我们计算周期长度为i时,计算的总的方案数包括了i的所有约数周期的情况,为了避免重复减去,因此我们计算完每个周期长度的方案数要减去其约数周期的方案数,代码我感觉我写的还是蛮容易搞懂的,做完这题DP技能+1。
#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <string>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <utility>#include <algorithm>#include <functional>using namespace std;typedef long long ll;const int maxn = 1010;const int mod  = 1000000000 + 7;char  str[maxn];int C[maxn][maxn], dp[maxn][maxn], dp1[2][maxn];void init() {    memset(C, 0, sizeof(C));    C[0][0] = 1;    for(int i = 1; i <= 1000; ++i) {        C[i][0] = C[i][i] = 1;        for(int j = 1; j < i; ++j) {            C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;        }    }}int main() {    //freopen("aa.in", "r", stdin);    init();    int T, N, K;    int ans = 0;    scanf("%d", &T);    while(T--) {        scanf("%d %d", &N, &K);        scanf("%s", str);        ans = 0;        for(int i = 0; i <= K; ++i) {            ans = (ans + C[N][i]) % mod;        }        memset(dp, 0, sizeof(dp));        for(int i = 1; i < N; ++i) {            if(N % i == 0) {                int id = 0;                memset(dp1[0], 0, sizeof(dp1[0]));                dp1[0][0] = 1;                for(int j = 0; j < i; ++j) {                    memset(dp1[id^1], 0, sizeof(dp1[id^1]));                    int zero = 0;                    for(int k = j; k < N; k += i) {                        if(str[k] == '0') {                            zero++;                        }                    }                    for(int k = 0; k <= K; ++k) {                        if(k >= zero) {                            dp1[id^1][k] = (dp1[id^1][k] + dp1[id][k-zero]) % mod;                        }                        if(k >= (N/i)-zero) {                            dp1[id^1][k] = (dp1[id^1][k] + dp1[id][k-((N/i)-zero)]) % mod;                        }                    }                    id ^= 1;                }                for(int j = 0; j <= K; ++j) {                    for(int k = 1; k < i; ++k) {                        if(i % k == 0) {                            dp1[id][j] = ((dp1[id][j] - dp[k][j]) % mod + mod) % mod;                        }                    }                    ans = (ans - dp1[id][j]) % mod;                    dp[i][j] = dp1[id][j];                }            }        }        printf("%d\n", (ans % mod + mod) % mod);    }    return 0;}


0 0
原创粉丝点击