[hdu1028]整数拆分,生成函数

题意:给一个正整数n,求n的拆分方法数(不考虑顺序)

思路:不妨考虑用1~n来构成n。用多项式表示单个数所有能构成的数,用多项式表示,就相当于卷积运算了。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

#include <map>

#include <set>

#include <cmath>

#include <ctime>

#include <deque>

#include <queue>

#include <vector>

#include <cstdio>

#include <string>

#include <cstdlib>

#include <cstring>

#include <iostream>

#include <algorithm>

using namespace std;

#define X                   first

#define Y                   second

#define pb                  push_back

#define mp                  make_pair

#define all(a)              (a).begin(), (a).end()

#define fillchar(a, x)      memset(a, x, sizeof(a))

typedef long long ll;

typedef pair<intint> pii;

typedef unsigned long long ull;

#ifndef ONLINE_JUDGE

void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}

void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>

void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;

while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>

void print(const T t){cout<<t<<endl;}template<typename F,typename...R>

void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>

void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}

#endif

template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}

template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

template<typename T>

void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}

template<typename T>

void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}

const double PI = acos(-1.0);

const int INF = 1e9 + 7;

/* -------------------------------------------------------------------------------- */

int a[123], b[123];

int main() {

#ifndef ONLINE_JUDGE

    freopen("in.txt""r", stdin);

    //freopen("out.txt", "w", stdout);

#endif // ONLINE_JUDGE

    int n;

    while (cin >> n) {

        for (int i = 0; i <= n; i ++) a[i] = 1;

        for (int i = 2; i <= n; i ++) {

            fillchar(b, 0);

            for (int j = 0; j <= n; j ++) {

                for (int k = 0; k <= n / i; k ++) {

                    if (j + k * i > n) break;

                    b[j + k * i] += a[j];

                }

            }

            memcpy(a, b, sizeof(b));

        }

        cout << a[n] << endl;

    }

    return 0;

}

时间: 2024-10-25 12:52:49

[hdu1028]整数拆分,生成函数的相关文章

整数拆分问题的四种解法【转载】

http://blog.csdn.net/u011889952/article/details/44813593 整数拆分问题的四种解法 原创 2015年04月01日 21:17:09 标签: 算法 / 母函数定理 / 五边形数定理 / acm / 动态规划 整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分. 如果{m1,

【转载转载转载!】整数拆分问题的四种解法--尼奥普兰

整数拆分问题的四种解法 原创 2015年04月01日 21:17:09 标签: 算法 / 母函数定理 / 五边形数定理 / acm / 动态规划 整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分. 如果{m1,m2,m3,....,mi}中的最大值不超过m,即max{m1,m2,m3,....,mi} <= m,则称

整数拆分

将一个整数N拆分成n个连续自然数的和.例如: 15 = 1+2+3+4+5 15 = 4+5+6 15 = 7+8 实现一个函数,打印所有可能,并且统计有多少种方法? 分析过程如下. 对于一个数N, 2个自然数相加:m+(m+1)                                                                                                                  =2m+1 3个自然数相加:(m-1)+m

Pollard-Rho大整数拆分模板

随机拆分,简直机智. 关于过程可以看http://wenku.baidu.com/link?url=JPlP8watmyGVDdjgiLpcytC0lazh4Leg3s53WIx1_Pp_Y6DJTC8QkZZqmiDIxvgFePUzFJ1KF1G5xVVAoUZpxdw9GN-S46eVeiJ6Q-zXdei 看完后,觉得随机生成数然后和n计算gcd,可以将随机的次数根号一下.思想很叼. 对于里面说的birthday trick,在执行次数上我怎么看都只能减一半.只是把平均分布,变成了靠近0

poj 1221 UNIMODAL PALINDROMIC DECOMPOSITIONS 整数拆分

题意: 给一个数n,求有多少种和为n的单峰先增对称序列,比如当n=5时结果为3:(5), (1 3 1), (1 1 1 1 1). 分析: 转化为求类似整数拆分问题,f(i,j)的意义是把i进行拆分,最大数小于等于j的方法数. 代码: //poj 1221 //sep9 #include <iostream> using namespace std; const int maxN=300; __int64 a[maxN+10][maxN+10]; __int64 f(int m,int n)

poj 2229 完全背包变形(求解整数拆分问题)

整数拆分问题:给定一个正整数n,将n拆分为若干数字的和,问有多少种方法? 此题为整数拆分问题的子问题,拆分出的数字要求是2的幂次. 定义dp[i][k]表示枚举到第k个数字时数字i的拆分方案数. 则有状态转移方程: dp[i][k] = dp[i][k - 1] + dp[i - num[k]][k]; 熟悉完全背包的朋友可以看出,这个方程和完全背包的状态转移方程如出一辙,第二维可以省去,只要将i从小到大枚举即可. 1 #include <iostream> 2 #include <cs

poj 3014 Cake Pieces and Plates 整数拆分

题意: 将m拆成n个数,允许某个数为0,求拆分方案数. 分析: 裸的整数拆分,设h(m,n)表示将m拆成n个数,允许某数为0的方案数,递推方程见代码.很有意思的是,参考上一篇写poj1221的博文中,设f(m,n)表示将m进行任意份数不允许有0的整数拆分,且最大元素小于等于m的方案数,则h(m,n)==f(m,n)....求解此等式意义... 代码: //poj 3014 //sep9 #include <iostream> using namespace std; const int max

LightOJ 1336 Sigma Function(数论 整数拆分推论)

--->题意:给一个函数的定义,F(n)代表n的所有约数之和,并且给出了整数拆分公式以及F(n)的计算方法,对于一个给出的N让我们求1 - N之间有多少个数满足F(x)为偶数的情况,输出这个数. --->分析:来考虑F(x)为奇数的情况,给据题目中给我们的公式,,如果F(x)为奇数,那么这个多项式里面的任何一项都必须是奇数,可以知道p = 2时,        p^e - 1肯定是奇数,如果p != 2,当且仅当e为偶数的时候,此项为奇数,证明如下: 原式变形为[ p^(e+1) -p + (

LeetCode 343.整数拆分 - JavaScript

题目描述:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 题目分析 题目中"n 至少可以拆分为两个正整数的和",这个条件说明了 n 是大于 1 的整数. 对 7 来说,可以拆成 3+4,最大乘积是 12. 对 8 来说,可以拆成 3+3+2,最大乘积是 18. 解法 1: 动态规划 状态数组dp[i]表示:数字 i 拆分为至少两个正整数之和的最大乘积.为了方便计算,dp 的长度是 n + 1,值初始化为 1. 显然dp[2]等于