1. 程式人生 > >Sumsets(數學)

Sumsets(數學)

sum urn single 情況 arc mman num align 分解因子

Sumsets

Time Limit: 2000MS

Memory Limit: 200000K

Total Submissions: 14964

Accepted: 5978

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).

Input

A single line with a single integer, N.

Output

The number of ways to represent N as the indicated sum. Due to the potential huge size of this number, print only last 9 digits (in base 10 representation).

Sample Input

7

Sample Output

6

簡單的找規律的題,算不上DP

#include<cstdio>
const int maxn = 1000000 + 1;
int a[maxn];

int main()
{
	int n;	
	while(scanf("%d",&n)!=EOF)
	{
		int i,j;
		a[1] = 1;
		a[2] = 2;
		for(i=3; i<=maxn; i++)
		{
			if(i%2 == 1)
				a[i] = a[i-1];
			else
			{
				a[i] = a[i-2] + a[i/2];
				a[i] = a[i]%1000000000;	//? 
			}
		}		
		printf("%d\n",a[n]);
	}
	return 0;
} 

  

題解:可以直接列舉遞推:

n: ans:

1 1

2 2

3 2

4 4

5 4

6 6

7 6

8 10

9 10

10 14

11 14

12 20

...... ......

if(n&1) a[n]=a[n-1]

if(n%2==0) a[n]=(a[n-2]+a[n>>1])%1000000000

由上述遞推過程很容易發現遞推結果,不過可能會由於列舉的數字不多,只列舉了前7個,誤認為遞推關系是 if(n&1) a[n]=a[n-1]; if(n%2==0) a[n]=n 弱雞的我就是這麽想的(;′⌒`)。

還有一種利用二進制遞推的方式,討論區看來的啦:

可以將n用二進制表示.

n=1,只有1種表示方法。

n=2,10(2),二進制表示下,可以分拆成{1,1},{10}有兩種表示方法

n=3, 11(2),可以分拆成{1,1,1},{10,1}.

n=4, 100(2),{1,1,1,1},{10,1,1},{10,10},{100}.

.........

總結:如果所求的n為奇數,那麽所求的分解結果中必含有1,因此,直接將n-1的分拆結果中添加一個1即可 為s[n-1]
如果所求的n為偶數,那麽n的分解結果分兩種情況

1.含有1 這種情況可以直接在n-2的分解結果中添加兩個1即可,這種情況有 s[n-1]

2.不含有1 那麽,分解因子的都是偶數,將每個分解的因子都除以2,剛好是n/2的分解結果,並且可以與之一一對應,這種情況有 s[n/2]

Sumsets(數學)