HDU 2709 Sumset DP 二进制

原题连接

php

题意


  • 给咱们一个整数k,要求咱们将k分红若干个二的整数幂(1, 2, 4, 8...)的加和形式,问咱们全部的分法中,本质不一样(即某个2的幂的数量不一样)的形式有多少种,k最多为1000000,输出答案的后9位数

思路


  • 由k范围,咱们寻找线性算法,能够从题中给出的k == 7的例子来分析,以下图


    ios

  • 能够看到,因为7余2等于1,而1不可分解,因此每一行都有一个1,因此显然,咱们若是给7减去1以后,结果将仍然是6种,因此咱们能够发现,k为奇数时的结果就是k - 1的结果。

    算法

  • 而后咱们抛开最左边的一列1,从下往上看能够发现,第5 6行的全部数能够都除以2,而后得((1 1 1),(1 2)),这正是3的分解结果

    spa

  • 而再往上看1234行,咱们发现左边两列都是1,能够看作是第五行中,一个2分解的结果,因而忽略这两列,而后能够发现,从(1,1,1,1)到(4)正是4的分解结果,也就是6 - 2(由于忽略了两行1)的结果

    code

  • 考虑k等于其余偶数时,咱们能够发现上述状况是必定会有的 —— 咱们老是会分出一个最小值为2的序列,而后这个序列整体除以2,就是k / 2的分解结果,而后咱们将其中的一个2分解为2个1, 而后剩下的就是k - 2的分解结果,这样就包含了所有状况了

    blog

  • 因此k为奇数时, F[k] = F[k - 1]的答案,而k为偶数时,F[k] = F[k >> 1] + F[k - 2]

    get

提示


  • 这道题有提到single line,可是仍然有多组数据

    string

  • 虽然题目要求后9位,可是在此题中直接%1e9是没有问题的,多是出题人没有想到

    it

AC代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define lowbit(x) (x&(-x))

using namespace std;

const long long modd = 1000000000;

long long ff[1000005];
int n;

int main()
{
	ff[0] = 1;
	for (long long j = 1; j <= 1000000; ++j)
	{
		if (j & 1)
		{
			ff[j] = ff[j - 1];
		}
		else
		{
			ff[j] = ((ff[j] + ff[j - 2]) % modd + ff[j >> 1]) % modd;
		}
	}
	while (scanf("%d", &n) == 1)
	{
		printf("%lld\n", ff[n]);
	}
	return 0;
}
相关文章
相关标签/搜索