题意 把n拆分为2的幂相加的形式,问有多少种拆分方法。
思路 比较好的DP方案开始没有想到,所以这里列出两种方案吧
(1)DP(i,j)表示第i个数,最小数由2的j次方来组合得到的方案数。
状态转移dp[i][j] = (dp[i][j+1] + dp[i-(1<<j)][j])
初始条件 dp(1,0) = 1
(2)更好更简单的方法是分奇偶考虑,奇数时就是dp(i) = dp(i-1),偶数时dp(i) = dp(i-1)+dp(i/2)
dp(i-1)表示i由最小数由1来组合得到的方案数,比较好理解。
dp(i/2)表示i由最小数由2来组合得到的方案数,这是因为组成i/2的方案所有数乘2即是组成i的方案。
实现 这里就给出第一个方案的代码,第二个过于简单不列出了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
#define MAX 1000005
#define MOD 1000000000
int n;
int dp[MAX][20];
int main()
{
cin>>n;
int i,j;
dp[1][0] = 1;
int now = 1;
for(i=2;i<=n;i++)
{
if(i == (1<<now))
{
dp[i][now] = (dp[i][now] + 1) % MOD;
now++;
}
for(j=now-1;j>=0;j--)
{
if(i-(1<<j) < (1<<j))
continue;
dp[i][j] = (dp[i][j+1] + dp[i-(1<<j)][j])%MOD;
}
}
cout<<dp[n][0]<<'\n';
return 0;
}