划分整数

Posted blairgrowing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了划分整数相关的知识,希望对你有一定的参考价值。

 

题目描述

将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。

例如:n=7k=3,下面三种分法被认为是相同的。

1,1,5
1,5,1
5,1,1

问有多少种不同的分法。

输入格式

n,k (6<n200,2k6)

输出格式

1个整数,即不同的分法。

输入输出样例

输入 #1
7 3
输出 #1
4

说明/提示

四种分法为:
1,1,5
1,2,4
1,3,3
2,2,3

 

 代码:1采用深度优先算法

#include<iostream>
using namespace std;
int n,k,ans;
void dfs(int past,int cnt,int num){
    if (cnt==1)
    {
        ans++;
        return ;
    }
    for (int i = past; i <= num/cnt; i++)
        dfs(i,cnt-1,num-i);    
}
int main(){
    cin>>n>>k;
    dfs(1,k,n);
    cout<<ans<<endl;
}

 

代码2:采用dp的方法

f[i][x] 表示 i 分成 x 个非空的数的方案数。

显然 i<x 时 f[i][x]=0 , i=x 时 f[i][x]=1;

其余的状态,我们分情况讨论:

①有1的 ②没有1的

第一种情况,方案数为 f[i-1][x-1]

第二种情况,方案数为 f[i-x][x] (此时 i 必须大于 x)

所以,状态转移方程为: f[i][x]=f[i-1][x-1]+f[i-x][x]

 

代码2:动态规划dp

#include<bits/stdc++.h>
using namespace std;
int n,k,f[201][7];  //f[k][x] k 分成 x 份 ={f[k-1][x-1],f[k-x][x]}
int main(){
    cin >> n >> k;
    for (int i=1;i<=n;i++) {
        f[i][1]=1;
        f[i][0]=1;
    }
    for (int x=2;x<=k;x++) {
        f[1][x]=0;
        f[0][x]=0;
    }  // 边界,为了防止炸,我把有0的也处理了
    for (int i=2;i<=n;i++){
        for (int x=2;x<=k;x++)
            if (i>x) {
                f[i][x]=f[i-1][x-1]+f[i-x][x];
            else 
                f[i][x]=f[i-1][x-1];
    }
    cout<<f[n][k];
    return 0;
}

 

代码3:母函数

技术图片

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>

#define max(A, B) ((A > B) ? A : B)//习惯携带,自行忽略 (*?▽?*)
#define min(A, B) ((A > B) ? B : A)

int main()
{
    freopen("Hardict_in.txt", "r", stdin);
    freopen("Hardict_out.txt", "w", stdout);
    int n, dv;
    int i, j, k, l;
    int value[233][233], temp[233][233] = { 0 };
    scanf("%d%d", &n, &dv);

    memset(value, 0, sizeof(value));
    for (i = 0; i <= dv; i++)
        value[i][i] = 1;//初始化,全为1可行(设置边界)

    for (i = 2; i < n; i++) {
        for (j = 0; j <= n; j++)
            for (l = 0; l <= dv; l++)//取到dv就停止
                for (k = 0; k + j <= n; k += i)
                    temp[k / i + l][k + j] += value[l][j];//如果不能理解可以试试写写或看一维的(推荐自己写几项,一维的我贴在下面了)

        for (l = 0; l <= dv; l++){
            for (j = 0; j <= n; j++){
                value[l][j] = temp[l][j];
                //printf("%d ",value[l][j]);
            }
            //printf("%d   
",l)可以打表观察变化
        }
                }
        memset(temp, 0, sizeof(temp));//temp设置为0,进行x^(i+1)系列的读入
    }

    printf("%d", value[dv][n]);
    return 0;
}

一维的:

int n, value[2333], temp[2333];
    int i, j, k;
    scanf("%d", &n);

    for (i = 1; i <= n; i++)
        value[i] = 1; //x^1时,即第一个括号中

    for (i = 2; i <= n; i++) {
        memset(temp, 0, sizeof(temp));
        for (j = 0; j <= n; j++)
            for (k = 0; k + j <= n; k += i)
                temp[k + j] += value[j];

        for (j = 0; j <= n; j++)
            value[j] = temp[j];
    }
    printf("%d", value[n]);//这里求的是所有能构成n的划分个数

 

 

 

 

 

 

 

G(x)=(1+yx+y2x2+y3x3+y4x4+.....)(1+yx2+y2x4+y3x6+y4x8+......)(1+yx3+y2x6+y3x9+....)........(1+yxn)

以上是关于划分整数的主要内容,如果未能解决你的问题,请参考以下文章

动态规划整数划分及其变种

Java 求解划分字母区间

763. 划分字母区间

Leetcode 763 划分字母区间

贪心算法:划分字母区间

763.划分字母区间