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
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(數學)