牛客网:整数拆分【灵活dp】

在这里插入图片描述

思路分析

思路其实很简单,没必要强行找规律其实是找不到,dp无疑是很快的一种做法。首先预处理出所有的0-19之间的2的幂次,因为输入数据小于1000000,所以2^19完全够用。记这个数组为a。

  • dp[i][j]:使用a数组前i个元素凑出数字j的总方案数,那么我们的状态转移方程直观上来说就是 (使用前i-1个元素凑出j的方案数加上使用前i个元素凑出j-a[i]的数目)dp[i][j]=dp[i-1][j]+dp[i][j-a[i]]
  • 强行使用了滚动数组进行优化,ԾㅂԾ,,其实不用也没关系只是我写顺手了而已。
#include<iostream>
#include<map>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<string.h>
using namespace std;

#define MAX 1000005
#define ll int
#define mod 1000000000

// dp[i][j]:使用前i个元素凑成j的种数  滚动数组优化
ll a[20], dp[MAX];
int main() {
	ll n;
	for (int i = 0; i < 20; i++)
		a[i] = 1 << i;
	
	while (scanf("%d", &n) != EOF) {
		memset(dp, 0, sizeof(dp)); dp[0] = 1;

		for (int i = 0; i < 20 && a[i] <= n; i++) {
			for (int j = a[i]; j <= n; j++) {
				//dp[i][j]=dp[i-1][j]+dp[i][j-a[i]] 由于滚动数组 dp[j]本身就继承了dp[i-1][j]
				dp[j] += dp[j - a[i]];
				dp[j] = dp[j] % mod;
			}
		}
		printf("%d\n", dp[n]);
	}
}
发布了269 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105610291