【整數划分系列】


1.nyoj90

描述

將正整數n表示成一系列正整數之和:n=n1+n2+…+nk, 
其中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
【思路】
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;  
}  
View Code

因為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;  
    }  
}  
View Code

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;  
}
View Code

 

3.nyoj279:隊花的煩惱

描述

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;  
}
View Code

4.51nod1201整數划分

將N(N<=50000)分為若干個不同整數的和,有多少種不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2,3},共4種。由於數據較大,輸出Mod 10^9 + 7的結果即可。

開始想的dp[i][j]代表j的最大划分數不超過i,但是數組需要開很大。
換個思路就是dp[i][j]代表j划分成i個整數的方法數,也分有1還是沒有1,跟上面第2題有點類似,但是還要求划分成不同的整數,所以方程為dp[i][j] = dp[i][j-i](無1) + dp[i-1][j-i](有1且僅有1個1)
認真思考會發現i不會超過320,利用等差數列求和求出

#include <bits/stdc++.h>
using namespace std;
const int N = 50000;
const int mod = 1e9+7;
typedef long long LL;
LL dp[322][N+4];
int main()
{
    int n;
    for(int j = 1; j <= N; j++) dp[1][j] = 1;
    for(int i = 2; i <= 320; i++)
        for(int j = 1; j <= N; j++)
        {
            if(i >= j) continue;
            else dp[i][j] = (dp[i][j-i] + dp[i-1][j-i])%mod;
        }
    while(~scanf("%d", &n))
    {
        int sum = 0, ans = 0;
        for(int i = 1; i <= 320; i++)
        {
            ans = (ans + dp[i][n]) % mod;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM