H:
这道题直接推到一个递推公式不是很容易但是可以一个一个拆分
例如样例7;从大到小向外拆分2的幂
找到比7小的最大的2的幂是4,
如果拆出4,可以继续往后统计3的拆分但不会拆出比4大的数的个数(3=2+1=1+1+1)
如果拆出2,可以继续往后统计5拆分但是不比2大的数的个数(5=2+2+1=2+1+1+1=1+1+1+1+1)
如果拆出1,可以继续往后统计6拆分但是不比1大的数的个数(6=1+1+1+1+1+1)
而后我们发现不比2的n次幂大的数这个限制可以用背包来解决,将2的n次幂放到外面当做背包dp的物品循环,而且拆分结果会出现若干同样数的情况,所以是完全背包dp,接下来看代码实现(很简单的)
#include<bits/stdc++.h>
using namespace std;
long long sum[100],dp[1000001];
int n,ans,mod=1e9+7;
void chuli(){
int p=1;
while(p<=n){
sum[ans++]=p;
p=p<<1;
}
}
int main(){
cin>>n;
chuli();
dp[0]=1;
for(int i=0;i<ans;i++){
for(int j=sum[i];j<=n;j++){
dp[j]=(dp[j]+dp[j-sum[i]])%mod;
}
}
cout<<dp[n];
return 0;
}