P1025 [NOIP2001 提高组] 数的划分题解

Posted zhangtingxi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1025 [NOIP2001 提高组] 数的划分题解相关的知识,希望对你有一定的参考价值。

题目链接

题目

将整数 \\(n\\) 分成 \\(k\\) 份,且每份不能为空,任意两个方案不相同(不考虑顺序)。

例如:\\(n=7\\)\\(k=3\\),下面三种分法被认为是相同的。

\\(1,1,5\\);
\\(1,5,1\\);
\\(5,1,1\\).

问有多少种不同的分法。

思路

首先我们可以打出一个暴力。然而为了防止重复,我们可以规定每次枚举出的这个数要大于等于上一个数。

然后只有40分。

考虑剪枝。

  1. 建设剩下的 \\(n\\) 要分成 \\(k\\) 份,每份大小至少为 \\(v\\)。那么如果 \\(n\\leqslant k\\times v\\),剩下的必然不够分。
  2. 然后我们发现好像还超时,于是我们尝试规定每次枚举的数都要大于上一个数,那我们在枚举当前数的时候同时枚举他出现次数就行了。
  3. 然后这样只有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;



以上是关于P1025 [NOIP2001 提高组] 数的划分题解的主要内容,如果未能解决你的问题,请参考以下文章

洛谷-----P1025 [NOIP2001 提高组] 数的划分

[NOIP·2001普及组] 数的划分

codevs——1039 数的划分

dp练习——数的划分

codevs 1039 数的划分

codevs 1039 数的划分 x