这是来自spoj的problem状态
对于n位x1,x2,x3,...,Xn的字符串 字符串的相邻位数 (AdjBC(x))由
给出X1 * X2 + X2 * X3 + X3 * X4 + ... + Xn-1 * XN
计算1的次数 bit与另一个1位相邻。对于 例如:
AdjBC(011101101)= 3
AdjBC(111101101)= 4
AdjBC(010101010)= 0
,问题是:编写一个程序,它将整数n和k作为输入,并返回满足AdjBC(x)= k的n位(2位中的2位)的位串数x。
我不知道如何解决这个问题。你能帮帮我解决这个问题吗?
由于
答案 0 :(得分:8)
通常在组合问题中,查看它产生的一组值会有所帮助。使用蛮力我计算了下表:
k 0 1 2 3 4 5 6
n +----------------------------
1 | 2 0 0 0 0 0 0
2 | 3 1 0 0 0 0 0
3 | 5 2 1 0 0 0 0
4 | 8 5 2 1 0 0 0
5 | 13 10 6 2 1 0 0
6 | 21 20 13 7 2 1 0
7 | 34 38 29 16 8 2 1
第一列是熟悉的Fibonacci序列,并且满足递归关系f(n, 0) = f(n-1, 0) + f(n-2, 0)
其他列满足递归关系f(n, k) = f(n - 1, k) + f(n - 1, k - 1) + f(n - 2, k) - f(n - 2, k - 1)
有了这个,你可以做一些动态编程:
INPUT: n, k
row1 <- [2,0,0,0,...] (k+1 elements)
row2 <- [3,1,0,0,...] (k+1 elements)
repeat (n-2) times
for j = k downto 1 do
row1[j] <- row2[j] + row2[j-1] + row1[j] - row1[j-1]
row1[0] <- row1[0] + row2[0]
swap row1 and row2
return row2[k]
答案 1 :(得分:7)
作为提示,您可以将其分为两种情况:数字以0结尾,数字以1结尾。
def f(n, k):
return f_ending_in_0(n, k) + f_ending_in_1(n, k)
def f_ending_in_0(n, k):
if n == 1: return k == 0
return f(n - 1, k)
def f_ending_in_1(n, k):
if n == 1: return k == 0
return f_ending_in_0(n - 1, k) + f_ending_in_1(n - 1, k - 1)
这样可以提供正确的输出,但需要很长时间才能执行。您可以应用标准动态编程或记忆技术,以使其足够快地执行。
答案 2 :(得分:4)
我参加聚会很晚,但是我有一个线性的时间复杂度解决方案。
对我来说,这更多是一个数学问题。您可以在我撰写的blog post中阅读详细的解决方案。接下来是一个简短的概述。我希望可以放一些LaTeX,但是SO不允许这样做。
假设对于给定的n
和k
,我们的答案由函数f(n,k)
给出。使用乞eg的方法,我们可以得出以下公式
f(n,k) = SUM C(k+a-1,a-1)*C(n-k+1-a,a)
,其中a
从1
到(n-k+1)/2
C(p,q)
表示二项式系数。
因此,要获得答案,我们必须为a
的每个值计算两个二项式系数。我们可以事先计算出二项式表。由于必须计算表格,因此该方法将在O(n^2)
中给出答案。
我们可以使用递归公式C(p,q) = (p * C(p-1,q-1))/q
从上一循环中的二项式系数的当前值中计算出当前值,从而改善时间复杂度。
我们的最终代码如下:
long long x=n-k, y=1, p=n-k+1, ans=0;
ans += x*y;
for(int a=2; a<=p/2; a++)
{
x = (x*(p-2*a+1)*(p-2*a+2))/(a*(p-a+1));
y = (y*(k+a-1))/(a-1);
ans += x*y;
}
您可以在我的GitHub repository中找到完整的可接受的解决方案。