给定一个长度为N且仅由0和1组成的字符串。但是字符串的某些位置是'?'。这意味着它们可以放0或1。
现在,问题是我们需要计算填充这些内容的方法数量?'可以将No K 0组合在一起的位置。
比如说我们有长度为N = 4且字符串为0 ?? 0的字符串
然后让K = 3然后在这里我们可以把' 0'仅在两个最大的一个位置。所以字符串是:
0100
0010
0110
所以这里的回答是3.现在给定长度为N和K的字符串,我们需要计算制作这个字符串的方法的数量。
我的方法:
现在我正在采用O(N,K)方法来解决这个问题,使用动态编程,如果我们将0放在第i位置,那么我们可以将K-1零放在'?&#39的下一个连续段中;如果我们放1,那么我们可以再次使用K零。
但N和K可能非常大。那么它们是一些更好,更有效的算法吗?
其中一个答案中提到的代码:
int n,k;
cin>>n>>k;
string s;
cin>>s;
s="#"+s;
int size=s.length();
vector<long long int>F(size+1);
F[0]=1;
for(int i=1;i<=size;i++){
if(s[i]=='R')
{
F[i]=0;
}
else if(s[i]=='L'){
F[i]=1;
}
else{
for(int j=i-1;j>=i-k;j--){
if(j<0)
break;
F[i]=(F[i]+F[j])%MOD;
}
}
}
cout<<F[size]<<"\n";
现在它的测试用例没那么大了。但是我在abrute force解决方案上运行它并没有匹配。
测试案例:n = 73,k = 7,字符串s = L?R?LLL?L?L?L?LLL L ??? RL?LR?L? LLRL ?? R 111 L&RL ???? RL?R 10 LL ?? LLLR·R
答案应该是877905026.但是代码是246470268
答案 0 :(得分:1)
您可以使用数组F [n]来计算填充位置[0,n]的方式的数量,使得没有K连续的0并且在位置n-1处存在1。
然后根据先前的结果计算F [n + 1],我们知道在位置n处有1,在0和K-1之前存在零。设零的数量为k。
F[0] = 1
F[n] = sum F[n-1-k] for k in 0,1,..,K-1
(only including values for k up to where the string at n-1-k is forced to be 1)
这应该给出正确答案,但需要时间O(NK)。
但是,我们可以通过维持F [n]的值的前缀和来加速和的计算。换句话说,如果我们存储一个数组S [n] = F [0] + F [1] + F [2] + .. + F [n],我们可以通过减去快速计算F的特定指数的总和两个S [n]值。
因此,通过跟踪强制1的最后位置,您可以计算O(N)中的重现。
最终答案将由F [N + 1]给出。
对于K = 3的示例和0 ?? 0的字符串:
F[0] = 1 (Just the empty string)
F[1] = 0 : position n-1=0 is forced to be 0 so no solutions are possible
F[2] = F[1]+F[0] = 1 (Just the string 01)
F[3] = F[2]+F[1]+F[0] = 2 (The strings 001 and 011)
F[4] = 0 : position n-1=3 is forced to be 0 so no solutions possible
F[5] = F[4]+F[3]+F[2] = 3 (the strings 0010 and 0110 and 0000)
所以最后的答案是3
对于你的第二个例子10 ??? 0 ??
F[0] = 1 (empty string)
F[1] = 1 (The string 1)
F[2] = 0
F[3] = F[2]+F[1] = 1 (The string 101)
F[4] = F[3]+F[2]+F[1] = 2 (The strings 1011 and 1001)
F[5] = F[4]+F[3]+F[2] = 3 (10011 and 10111 and 10001)
F[6] = 0
F[7] = F[6]+F[5]+F[4] = 5 (1011001, 1001001, 1001101, 1011101, 1000101)
F[8] = F[7]+F[6]+F[5] = 8 (10110011, 10010011, 10011011, 10111011, 10001011, 10011001, 10111001, and 10001001)
F[9] = F[8]+F[7]+F[6] = 13
10110011, 10010011, 10011011, 10111011, 10001011, 10011001, 10111001, 10001001
10110010, 10010010, 10011010, 10111010, 10001010
你的代码几乎是正确的:内部循环改变如下,它给你想要的答案:
if(s[i]=='R')
{
F[i]=0;
} else{
for(int j=i-1;j>=i-k;j--){
if(j<0)
break;
F[i]=(F[i]+F[j])%MOD;
if (s[j]=='L')
break;
}
}