1.nyoj90
描述
其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表示称为正整数n的划分。求正整数n的不
同划分个数。
例如正整数6有如下11种不同的划分:
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
-
输入
- 第一行是测试数据的数目M(1<=M<=10)。以下每行均包含一个整数n(1<=n<=10)。 输出
- 输出每组测试数据有多少种分法。 样例输入
-
1 6
样例输出
-
11
-
ACM队队花C小+最近在X大OJ上做题,竟发现了一道做不出来的…水题!她快郁闷死了……也许是最近状态不太好吧……她希望大家能帮帮忙:把一个整数分成若干个不为零的整数,问有多少种不同分法。
例:7 3 其中的分法:1 1 5,1 5 1,5 1 1是同一种分法。
-
输入
-
有多组测试数据
每组数据都有两个整数n,m(6<=n<=500,2<=m<=6)
n表示该整数,m表示把n分成m份
输出
-
对每一组测试数据,输出不同的分法数
样例输入
-
7 3 10 2 20 3
样例输出
-
4 5 33
注意m<=6即可
#include<bits/stdc++.h> using namespace std; int dp[505][8]; int main() { int n,m,i,j; dp[1][1]=1; for(i=2; i<=500; i++) for(j=1; j<=i&&j<=6; j++) { if(i==j||j==1) dp[i][j]=1; else dp[i][j]=dp[i-1][j-1]+dp[i-j][j]; } while(~scanf("%d%d",&n,&m)) { printf("%d\n",dp[n][m]); } return 0; }
-
有多组测试数据
开始的错误思路:dp[i][j]代表整数i划分的个数不超过j的划分数,但是这样做会有重复划分例如3有3、1+2、2+1、1+1+1。
dp[1][1]=1; for(i=1; i<=10; i++) for(j=1; j<=10; j++) { if(j==1) dp[i][j]=1; else if(j>i) dp[i][j]=0; else if(j==i) dp[i][j]=1+dp[i][j-1]; else dp[i][j]=dp[i-1][j-1]+dp[i-1][j];//含单独一个划分和不含单独一个划分 }
正确做法如下:dp[i][j]代表整数i划分的所有数中最大数不超过j的划分数。
#include<bits/stdc++.h>
using namespace std;
int dp[15][15];
int main()
{
int n,m,i,j,t;
dp[1][1]=1;
for(i=1; i<=10; i++)
for(j=1; j<=10; j++)
{
if(j==1) dp[i][j]=1;
else if(i>j) dp[i][j]=dp[i-j][j]+dp[i][j-1];//含j和不含j
else if(i==j) dp[i][j]=1+dp[i][j-1];
else dp[i][j]=dp[i][i];
}
cin>>t;
while(t--)
{
scanf("%d",&n);
printf("%d\n",dp[n][n]);
}
return 0;
}
因为n很小不超过10,可以用递归写,最多算10!也不会TLE,下面是dfs:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
int n,ans;
void dfs(int i,int s)
{
if(s>n) return;
if(s==n)
{
ans++;
return;
}
for(i; i<=10; i++)//保证每次加的数大于等于原来的
{
dfs(i,s+i);
}
}
int main()
{
int m;
cin>>m;
while(m--)
{
ans=0;
cin>>n;
dfs(1,0);
cout<<ans<<endl;
}
}
2.nyoj176:n划分成m个整数的和
dp[i][j]代表i划分成j个数
#include<bits/stdc++.h>
using namespace std;
int dp[105][108];
int main()
{
int n,m,i,j,t;
dp[1][1]=1;
for(i=2; i<=100; i++)
for(j=1; j<=i; j++)
{
if(i==j||j==1) dp[i][j]=1;
else dp[i][j]=dp[i-1][j-1]+dp[i-j][j];//含1和不含1
}
cin>>t;
while(t--)
{
scanf("%d%d",&n,&m);
printf("%d\n",dp[n][m]);
}
return 0;
}