• 【整数划分系列】


    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
    ",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
    ",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
    ",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
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    跟风!发一篇我常用VS开发技巧
    引用:程序员最常犯的五大非技术性错误
    Introduction to the Oracle Database 3
    Oracle Database 12c 12大新特性详解
    Streams全库复制
    Introduction to the Oracle Database 2
    Oracle FlashBack
    Oracle Database Features 2
    Oracle Database Features
    TNSName配置小结
  • 原文地址:https://www.cnblogs.com/lesroad/p/8891841.html
Copyright © 2020-2023  润新知