题目大意:给你一个数n,只能用2的幂次求和组成,问总共有多少种方案,答案保留九位数。n<1000000.
思路1:递推。因为每个数n的答案ans[n]都是由ans[n-(1<<i)]组成的,而2的19次方就是五十多万,所以只需要O(19*1000000)打表即可,时间好像用的有点多
思路2:dp。每个状态dp[i]可有两种状态得来,一种是dp[i] = dp[i-1] , 另一种是(dp[i-1) + dp[i>>1])得来。前者是i为奇数时的状态转移,后者是偶数时。对于奇数i来说,是(i-1)增加了1,而且除以2以后和(i-1)/2相等,所以他的所有情况和(i-1)的情况相同,而对于偶数i来说,他在dp[i-1]的基础上增加了一种新的组合方式,即dp[i>>1]
代码1:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
#define maxn 1000005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000
int ans[maxn];
int fac[20];
void init()
{
mem(ans , 0);
for(int i = 0 ; i < 20 ; i ++) fac[i] = (1 << i);
ans[0] = 1;
for(int i = 0 ; i < 20 ; i ++)
{
for(int j = fac[i] ; j < maxn ; j ++)
{
ans[j] = (ans[j]+ans[j-fac[i]]) % INF;
}
}
}
int main()
{
int n;
init();
while(scanf("%d" , &n) != EOF)
{
printf("%d\n" , ans[n]);
}
return 0;
}
代码2:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
#define maxn 1000005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000
int dp[maxn];
void init()
{
mem(dp , 0);
dp[0] = 1;
for(int i = 1 ; i < maxn ; i ++)
{
if(i & 1) dp[i] = dp[i-1];
else dp[i] = ( dp[i-1] + dp[i >> 1] ) % INF;
}
}
int main()
{
int n;
init();
while(scanf("%d" , &n) != EOF)
{
printf("%d\n" , dp[n]);
}
return 0;
}