博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 4671 Partition(DP,整数划分,5级)
阅读量:5221 次
发布时间:2019-06-14

本文共 3863 字,大约阅读时间需要 12 分钟。

Partition

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 114    Accepted Submission(s): 46

Problem Description
How many ways can the numbers 1 to 15 be added together to make 15? The technical term for what you are asking is the "number of partition" which is often called P(n). A partition of n is a collection of positive integers (not necessarily distinct) whose sum equals n.
Now, I will give you a number n, and please tell me P(n) mod 1000000007.
 

 

Input
The first line contains a number T(1 ≤ T ≤ 100), which is the number of the case number. The next T lines, each line contains a number n(1 ≤ n ≤ 10
5) you need to consider.
 

 

Output
For each n, output P(n) in a single line.
 

 

Sample Input
 
4 5 11 15 19
 

 

Sample Output
 
7 56 176 490
 

 

Source
 

 

Recommend
zhuyuanchen520

 

根本就不会嘛公式谁会推啊,写个DP超,果断搜公式爆搜,终于找到了维基百科的公式了,结果题解给的就是这个网站。哎!这就一公式。

 

 

#include
#include
#include
#define FOR(i,a,b) for(int i=a;i<=b;++i)#define clr(f,z) memset(f,z,sizeof(f))#define LL __int64using namespace std;const int mm=1e5+9;const LL mod=1000000007;LL dp[mm],f[mm];void getdata(){ int zt=1000; FOR(i,-1000,1000)f[i+zt]=i*(3*i-1)/2; dp[0]=1; FOR(i,1,mm-1) { dp[i]=0; FOR(j,1,i) { if(f[j+zt]<=i) { if(j&1) { dp[i]+=dp[i-f[j+zt]]; } else dp[i]-=dp[i-f[j+zt]]; } else break; dp[i]=(dp[i]%mod+mod)%mod; if(f[zt-j]<=i) { if(j&1) { dp[i]+=dp[i-f[zt-j]]; } else dp[i]-=dp[i-f[zt-j]]; } else break; } dp[i]=(dp[i]%mod+mod)%mod; }}int main(){ int cas; getdata();int n; while(~scanf("%d",&cas)) { while(cas--) { scanf("%d",&n); printf("%I64d\n",dp[n]); } } return 0;}

背包版本

#include
#include
#include
#include
using namespace std;int a[100001];int main(){ //freopen("data.txt","w",stdout); int lim = 10000; a[0] = 1; for(int i=1;i<=lim;i++) for(int j=0;j+i<=lim;j++){ a[i+j] = (a[i+j] + a[j]); if (a[i+j] >= 1000000007) a[i+j] -= 1000000007; } int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); printf("%d\n",a[n]); } return 0;}

递归版本

#include
#include
#include
#define FOR(i,a,b) for(int i=a;i<=b;++i)#define clr(f,z) memset(f,z,sizeof(f))#define LL __int64using namespace std;const int mm=1e5+9;const LL mod=1000000007;const int cd=1000;LL dp[mm][cd];LL Part(LL n,LL m){ if ((n < 1)||(m < 1)) return 0; if ((n == 1)||(m == 1)) return 1; if(m<1000&&dp[n][m]!=-1)return dp[n][m]; LL ret=0; if (n < m) {ret=Part(n, n); ret%=mod; if(m<1000)dp[n][m]=ret; return ret; } if (n == m) {ret=Part(n, m-1) + 1; ret%=mod; if(m<1000)dp[n][m]=ret; return ret; } ret=Part(n, m-1) + Part(n-m, m); ret%=mod; if(m<1000)dp[n][m]=ret; return ret;}int main(){ int cas,n; clr(dp,-1); while(~scanf("%d",&cas)) { while(cas--) { //scanf("%d",&n); FOR(i,1,50) { n=i; printf("%d %I64d\n",i,Part(n,n)); } } } return 0;}

 

整数划分,求每个划分。

void print_partition(int n){  int i = 1;  int m = 1;  int h = 1;  int t, r;  int a[n + 1];   for (; i < n + 1; ++i) a[i] = 1;  a[1] = n;  printf("%d \n", a[1]);   while (a[1] != 1)  {    if (a[h] == 2)    {      a[h--]--;      m++;    }    else    {      r = --a[h];      t = m - h + 1;       while (t >= r)      {        a[++h] = r;        t -= r;      }      if (t == 0) m = h;      else m = h + 1;      if (t >= 2) a[++h] = t;    }    for (i = 1; i < m + 1; i++)      printf("%d ", a[i]);    printf("\n");  }}

 

 

转载于:https://www.cnblogs.com/nealgavin/p/3797616.html

你可能感兴趣的文章
js 时间对象方法
查看>>
网络请求返回HTTP状态码(404,400,500)
查看>>
Spring的JdbcTemplate、NamedParameterJdbcTemplate、SimpleJdbcTemplate
查看>>
Mac下使用crontab来实现定时任务
查看>>
303. Range Sum Query - Immutable
查看>>
图片加载失败显示默认图片占位符
查看>>
【★】浅谈计算机与随机数
查看>>
[转载]宇宙文明等级的划分标准
查看>>
《代码阅读方法与实现》阅读笔记一
查看>>
解决 sublime text3 运行python文件无法input的问题
查看>>
javascript面相对象编程,封装与继承
查看>>
Atlas命名空间Sys.Data下控件介绍——DataColumn,DataRow和DataTable
查看>>
Java中正则表达式的使用
查看>>
算法之搜索篇
查看>>
新的开始
查看>>
java Facade模式
查看>>
NYOJ 120校园网络(有向图的强连通分量)(Kosaraju算法)
查看>>
SpringAop与AspectJ
查看>>
Leetcode 226: Invert Binary Tree
查看>>
http站点转https站点教程
查看>>