数的划分 题解
深搜
轻而易举可以看出,本题转化为数学模型就是把一个大于
即求不定方程
那就可以依次枚举
可是如果直接搜索的话,运行速度会很慢,所以我们要考虑剪枝。
我们发现,枚举
所以设 int f[9]
,该数组记录枚举的方案数,扩展第
所以我们就可以写出
#include<bits/stdc++.h> #define int long long//重点:十年OI一场空,不开 long long 见祖宗(doge using namespace std; int ans,n,f[9]={0,1},k;//初始化f[1]=1,因为第一个数最低一定是1 inline void dfs(int p) { if(n==0) return;//如果n减完了,那就不用再减了 if(p==k)//如果累计加了k个数 { if(n>=f[p]) ans++;//如果分完了,答案+1 return; } for(int i=f[p];i<=n/(k-p+1);i++)//确定上下界 f[p+1]=i,n-=i,dfs(p+1),n+=i;//保存状态,搜索,回溯 return; } signed main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); //读入优化(然而并没有什么用) cin>>n>>k; dfs(1);//搜索,从第一个数开始 cout<<ans; return 0; }
计数
由于题目中 十分敏感地也可以设
我们分类讨论:
举个例子:假如现在有一个状态(
): 这 个数里面不含 ,我们就可以知道这个状态可以由 推出来,再由 表示的含义,得
综合以上,再加上初始化,得
//Or we can do this: #include<bits/stdc++.h> #define int long long using namespace std; int f[501][501];//f开全局,可以清零 signed main() { int n,k; cin>>n>>k; for(int i=1;i<=n;i++) { f[i][1]=1; f[i][0]=1; }//初始状态,根据常识可知:i个数选0或1个只有一种选法 for(int i=2;i<=n;i++) for(int x=2;x<=k;x++) if(i>x)//情况3 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];//n分成k个的方案数 return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】