数学专题题目练习整理
整数划分
P1025 数的划分
一看到这个题想到整数划分
但是他们有相似的地方但是不完全相同,对于之前的例题求“小于等于划分数所有的情况”,而该题是“等于划分数所有的情况”是有区别的。
不会存在i<j的情况。
照搬例题WA
#include <iostream>
using namespace std;
int dp[200][10];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1; i<=n; i++)
for(int j=1; j<=k; j++)
{
if(i==1||j==1) dp[i][j]=1;
else if(i<j) dp[i][j]=dp[i][i];
else if(i==j) dp[i][j]=1;
else if(i>j) dp[i][j]=dp[i-j][j-1]+dp[i][j-1];
}
// for(int i=1; i<=n; i++)
//for(int j=1; j<=k; j++)
// cout<<dp[i][j]<<" ";
cout<<dp[n][k]<<endl;
return 0;
}
这个题最后还是用动态规划做的
1.注意动态规划的初始化问题(根据题意来)
2.递推式找对:第一种有1,dp[【j-1】【i-1】
第二种无1,dp【i-j】【j】,就是将最后每位数再加一个,因为每一位不会出现0就不会出现1
#include <iostream>
using namespace std;
int dp[200][10];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1; i<=n; i++) dp[i][1]=1;
for(int i=1; i<=n; i++)
for(int j=2; j<=k; j++)
{
//else if(i==j) dp[i][j]=1;
if(i>=j) dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
// else dp[i][j]=0;
}
// for(int i=1; i<=n; i++)
//for(int j=1; j<=k; j++)
// cout<<dp[i][j]<<" ";
cout<<dp[n][k]<<endl;
return 0;
}
还有两种方式:搜索+剪枝;母函数,借此题也整理一下
2.搜索(dfs)+剪枝
#include <iostream>
using namespace std;
//搜索无非也是个递归的过程,纯纯学习别人家的代码
int n,k;
int dfs(int n,int p,int ii)//分别代表着待分配的数,分的部分数和当下要选出的数
{
if(p==1) return 1;//直到p==1,退出递归
int sum=0;//仔细想想为什么一定在函数内初始化呢,因为这里是递归呀,有return,其实已经保留了
for(int i=ii;i<=n/p;i++)//剪枝,因为枚举到n会有重复的情况
{
sum+=dfs(n-i,p-1,i);//这个很容易懂
}
return sum;
}
int main()
{
cin>>n>>k;
cout<<dfs(n,k,1)<<endl;
return 0;
}