划分整数
题目描述
将整数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 \n",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)
因上求缘,果上努力~~~~ 作者:图神经网络,转载请注明原文链接:https://www.cnblogs.com/BlairGrowing/p/12764777.html