HDU1028 整數劃分問題
Game of Connections
This is a small but ancient game. You are supposed to write down the numbers 1, 2, 3, ... , 2n - 1, 2n consecutively in clockwise order on the ground to form a circle, and then, to draw some straight line segments to connect them into number pairs. Every number must be connected to exactly one another. And, no two segments are allowed to intersect. It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right?
Input
Each line of the input file will be a single positive number n, except the last line, which is a number -1. You may assume that 1 <= n <= 100.
Output
For each n, print in a single line the number of ways to connect the 2n numbers into pairs.
Sample Input
2 3 -1
Sample Output
2 5
整數劃分問題是將一個正整數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
下面介紹一種通過遞迴方法得到一個正整數的劃分數。
遞迴函式的宣告為 int split(int n, int m);其中n為要劃分的正整數,m是劃分中的最大加數(當m > n時,最大加數為n),
1 當n = 1或m = 1時,split的值為1,可根據上例看出,只有一個劃分1 或 1 + 1 + 1 + 1 + 1 + 1
可用程式表示為 if(n == 1 || m == 1) return 1;
#include <stdio.h>
int split(int n, int m)
{
if(n < 1 || m < 1) return 0;
if(n == 1 || m == 1) return 1;
if(n < m) return split(n, n);
if(n == m) return (split(n, m - 1) + 1);
if(n > m) return (split(n, m - 1) + split((n - m), m));
}
int main()
{
printf("12的劃分數: %d", split(12, 12));
return 0;
}
直接遞迴計算可能會超時,所以考慮記憶化搜尋
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e3+7;
#define mod 1000000007
ll dp[130][130];
//n為要劃分的正整數,m是劃分中最大加數
void init()
{
memset(dp,-1,sizeof dp);
for(int i=1;i<130;i++)
dp[i][1]=dp[1][i]=1;
}
ll split(int n,int m)
{
if(dp[n][m]!=-1)
return dp[n][m];
if(n<1||m<1)
return dp[n][m]=0;
if(n==1||m==1)
return dp[n][1]=dp[1][m]=1;
if(m>n)//m>n,最大加數為n
return dp[n][n]=split(n,n);
if(m==n)
return dp[n][m]=split(n,m-1)+1;
if(m<n)
return dp[n][m]=split(n,m-1)+split(n-m,m);
}
int main()
{
init();
int n;
while(scanf("%d",&n)!=EOF){
printf("%lld\n",split(n,n));
}
return 0;
}