划分整数
Posted blairgrowing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了划分整数相关的知识,希望对你有一定的参考价值。
题目描述
将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5
1,5,1
5,1,1
问有多少种不同的分法。
输入格式
n,k (6<n≤200,2≤k≤6)
输出格式
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)
以上是关于划分整数的主要内容,如果未能解决你的问题,请参考以下文章