【P1025 [NOIP2001 提高组] 数的划分】题解
题目链接
题目
将整数 分成 份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:,,下面三种分法被认为是相同的。
;
;
.
问有多少种不同的分法。
思路
首先我们可以打出一个暴力。然而为了防止重复,我们可以规定每次枚举出的这个数要大于等于上一个数。
然后只有40分。
考虑剪枝。
- 建设剩下的 要分成 份,每份大小至少为 。那么如果 ,剩下的必然不够分。
- 然后我们发现好像还超时,于是我们尝试规定每次枚举的数都要大于上一个数,那我们在枚举当前数的时候同时枚举他出现次数就行了。
- 然后这样只有80分,我们尝试第1点中放到枚举过程里,然后就可以ac了。
总结
对于搜索剪枝的题目,我们可以超时考虑枚举的上下界。当还不行的时候,我们就把上下界放到枚举过程中,这能使程序运行效率大大增加。
Code
// Problem: P1025 [NOIP2001 提高组] 数的划分
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1025
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define mo
//#define N
//#define M
int n, m, i, j, k;
int f[210][10][10];
int dfs(int n, int k, int v)
{
if(n==k&&k==0) return 1;
if(k==0&&n) return 0;
if(n<v*k) return 0;
// if(f[n][k][v]!=-1) return f[n][k][v];
int ans=0;
for(int i=v; i*k<=n; ++i)
for(int j=1; j*i<=n&&j<=k; ++j)
ans+=dfs(n-i*j, k-j, i+1);
// return f[n][k][v]=ans;
return ans;
}
signed main()
{
// freopen("tiaoshi.in","r",stdin);
// freopen("tiaoshi.out","w",stdout);
memset(f, -1, sizeof(f));
n=read(); k=read();
printf("%lld", dfs(n, k, 1));
return 0;
}
本文来自博客园,作者:zhangtingxi,转载请注明原文链接:https://www.cnblogs.com/zhangtingxi/p/15704434.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战