[Usaco2005 Jan]Sumsets 求和

Description
Farmer John commanded his cows to search for different sets of numbers that sum to a given number. The cows use only numbers that are an integer power of 2. Here are the possible sets of numbers that sum to 7: 1) 1+1+1+1+1+1+1 2) 1+1+1+1+1+2 3) 1+1+1+2+2 4) 1+1+1+4 5) 1+2+2+2 6) 1+2+4 Help FJ count all possible representations for a given integer N (1 <= N <= 1,000,000).

给出一个N(1≤N≤10^6),使用一些2的若干次幂的数相加来求之.问有多少种方法

Input
一个整数N.

Output
方法数.这个数可能很大,请输出其在十进制下的最后9位.

Sample Input
7

Sample Output
6

HINT

  1. 1+1+1+1+1+1+1
  2. 1+1+1+1+1+2
  3. 1+1+1+2+2
  4. 1+1+1+4
  5. 1+2+2+2
  6. 1+2+4

考虑到n不大,所以我们可以直接用完全背包,复杂度应该是\(O(n\ln n)\)级别

其实发现奇数只能通过偶数+1得到,而偶数可以通过奇数+1,也可以通过其折半的偶数翻倍得来,因此得到方程

\[f[i]=\begin{cases} f[i-1]&,i\%2=1\\ f[i-1]+f[i/2]&,i\%2=0\end{cases} \]

复杂度\(O(n)\)

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
	int x=0,f=1;char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline int read(){
	int x=0,f=1;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)    putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=1e6,p=1e9;
int f[N+10];
int main(){
	int n=frd(); f[0]=1;
	for (register int i=1;i<=n;i+=2)	f[i]=f[i-1],f[i+1]=(f[i]+f[(i+1)>>1])%p;
	printf("%d\n",f[n]);
	return 0;
}
posted @ 2018-11-21 10:45  Wolfycz  阅读(256)  评论(0编辑  收藏  举报