相邻位计数

时间:2011-02-27 11:48:39

标签: algorithm dynamic-programming

这是来自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。

我不知道如何解决这个问题。你能帮帮我解决这个问题吗?

由于

3 个答案:

答案 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不允许这样做。

假设对于给定的nk,我们的答案由函数f(n,k)给出。使用乞eg的方法,我们可以得出以下公式

f(n,k) = SUM C(k+a-1,a-1)*C(n-k+1-a,a),其中a1(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中找到完整的可接受的解决方案。