首页 > 其他分享 >数的划分 题解

数的划分 题解

时间:2022-08-24 18:03:52浏览次数:94  
标签:... le int 题解 枚举 long 划分 text


\(0.\) 写在前面

1.3【例题1】数的划分 - TuringEDU

P2706 数的划分 - TopsCoding

这题可以有两种写法:(至少两种)

  1. 深搜
  2. 计数 \(\text{DP}\)

接下来将会依次讲解


\(1.\) 深搜

轻而易举可以看出,本题转化为数学模型就是把一个大于 \(0\) 的整数 \(n\) 无序划分为 \(k\) 份的方案数

即求不定方程 \(x_1 + x_2 + x_3 + ...+ x_k = n,1 \le x_1 \le x_2 \le x_3 \le ... \le x_k\) 的解的个数

那就可以依次枚举 \(x_1 , x_2 , x_3 , ... , x_k\) 的值,再加以判断。

可是如果直接搜索的话,运行速度会很慢,所以我们要考虑剪枝。

我们发现,枚举 \(x_1 , x_2 , x_3 , ... , x_k\) 的值有以下两个多次重复的地方:上界与下界

\(1.\) 由于枚举 \(x_1 , x_2 , x_3 , ... , x_k\) 中 \(x_1 , x_2 , x_3 , ... , x_k\) 值的重复概率很大,造成大量无效操作,所以我们考虑枚举依次递增

所以设 int f[9],该数组记录枚举的方案数,扩展第 \(i\) 个方案时的下界应是不小于前一个的值,即 \(f_{i-1} \le f_i\)

\(2.\) 假设我们将 \(n\) 已经分解为了 \(f_1,f_2,f_3...f_{i-1}\),时,则 \(f_i\) 的最大值应保证以后的 \(f_{i+1},f_{i+2}...f_n\) 都不下降,设 \(t=n-(f_1+f_2+...+f_{i-1})\) 所以 \(f_i\) 的上界是 \(\frac{t}{k-i+1}\)(\(k\) 表示一共分成多少块,题面提到过)

所以我们就可以写出 \(\text{AC Code}\) 了:

#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;
} 

\(2.\) 计数 \(\text{DP}\)

由于题目中 \(6 < n \le 200,2 \le k\le 6\) 因此我们十分敏感地也可以设 \(f_{i,j}\) 表示 \(i\) 个数,来分成 \(j\) 份的方案数

我们分类讨论:

\(1. i < j\) 时,数不够分,因此无解,但题目中说了不可能 \(i<j\),因此可以省略

\(2. i=j\) 时,刚好一种情况,够分,需要 \(f_{0,0}=1\)

\(3. i>j\) 时, 这是重点,我们考虑:

举个例子:假如现在有一个状态(\(k=3\)):\(\{2,2,3 \}\) 这 \(3\) 个数里面不含 \(1\),我们就可以知道这个状态可以由 \(\{1,1,2\}\) 推出来,再由 \(f_{i,j}\) 表示的含义,得 \(f_{i,j}=f_{i-j,j}+f_{i-1,j-1}\)

综合以上,再加上初始化,得 \(\text{AC Code2}\):

//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;
}

\(\huge\text{THE END}\)


标签:...,le,int,题解,枚举,long,划分,text
From: https://www.cnblogs.com/DreamerX/p/cutnum-solving.html

相关文章

  • 题解:【WC2005】双面棋盘
    【WC2005】双面棋盘题目链接这天做双面棋盘这道题,发现题解里面大多都是LCT,对于线段树套并查集的写法思路讲评很少而且不大清晰,因此有了这一篇题解。维护联通块的数量,......
  • has been blocked by CORS policy跨域问题解决
    title:hasbeenblockedbyCORSpolicy跨域问题解决我们在前端调用接口时,浏览器有时候会报错:XXXXformXXXXXhasbeenblockedbyCORSpolicy:No'Access-Control-......
  • CF1715F Crop Squares 题解
    CF1715FCropSquaressolution有一个\(n\timesm\)的长方形,四个角的坐标分别为$(0,0)$,$(0,m)$,$(n,0)$,$(n,m)$。在长方形里面有一个\(1\time......
  • CF838D题解
    很厉害的题。考虑将原本的座位串成一个环,然后加一个节点在\(1\)的前面\(n\)的后面。原问题等价为新节点不被座到的方案数。容易发现所有节点被座到和不被座到的方案......
  • 关于npm ERR! ERESOLVE could not resolve 问题解决
    1、问题描述从代码仓库拉取代码到本地,执行npminstall命令安装项目依赖,提示如下图错误  问题出现的原因由于npm版本问题,npm不同版本库之间命令不兼容。解决办法:执......
  • [2001年NOIP提高组] 数的划分
    为了确保出现过的方案不重复,可以规定在后面的分组中的数必须要大于前面分组中的数,x代表上一个出现过的数,初值为1,只要让下一个数从x开始循环,便可达成上述方案。s代表还需......
  • App 自动化测试实战技巧与经典面试题解析
    ⬇️点击“下方链接”,提升测试核心竞争力!>>更多技术文章分享和免费资料领取移动互联网时代,为了高效应对App多端发布、多版本发布、多机型发布等质量挑战,App自动化测试......
  • vue项目目录结构划分
     1.dist---编译之后的项目文件2.src---开发目录3.src/assets---静态资源src/assets/less---公共lesssrc/assets/img---图片资源4.src/components---组件5.src/pag......
  • [题解]轮流拿牌问题_一道博弈论笔试题(C++)
    题目A和B轮流从一个数组左右两端取数,A先B后,每次取一个数,最终取数总和大者获胜,两人每次都会选择最有利的策略,求获胜者取数的和。思路笔试时遇到的一道算法题,也是博弈论中......
  • ARC099F题解
    被杀了,记录一下好了。对于他那个数组是否相等,直接判断复杂度很高,考虑通过哈希映射之后判断是否相等。对数组的Hash可以类似字符串Hash那样去做。于是判断一个区间是......