P2119

luogu食用更佳

0.前言

如果你不知道怎么推式子,前面的人已经说的很清楚了,%%%
本题只要把式子推出来,一切都好说
因此,我只建议没听懂一长串balabala说怎么递推的蒟蒻比如我阅读这篇题解。

1.分析

先引用一下楼顶dalao的一段话:

首先可以发现每个 $x$ 都小于 $n$ ,而 $n$ 最大值只是15000,所以可以开一个桶来存每个魔法值出现的次数

回忆一下3个约束条件

$ xa<xb<xc<xd ① $

$ xb−xa=2(xd−xc) ② $

$ xb−xa<(xc−xb)/3 ③ $

现在魔改一下这三个式子

设$ t=xd−xc $

所以②可化为$ xb−xa=2t ④ $

将④代入③

$ 2t<(xc−xb)/3 $

移项一下,就变成

$ 6t<xc−xb ⑤ $

再魔改一下

设$ 6t+k=xc−xb $(就是把差的部分补上去)

于是可以画出来一个图

显然,$xa$ 的最小值为1,$xd$ 的最大值为n。


到这里,像我一样的蒟蒻还看得懂
但接下来

由图可得AD=9t+k所以我们可以尝试着枚举t用t来表示各个魔法值的值由上易得t的范围为1<=t<=(n?1)/9在代码中为了避免除法写成t?9<n再枚举D因为我们已经枚举出了t所以C的值是可以直接算出来的C=D?t又因为使ABCD满足条件的k的最小值为1,所以对于当前的C和D最大的A和B为……(省略200字)

不管你看没看懂,反正我没看懂。甚至写完还是不懂QAQ
所以,为了广大蒟蒻的人身安全,我决定解释一下枚举的过程。

2.实现

int main前,开数组

x[15005],f[40005],q[15005],qa[15005],qb[15005],da[15005],db[15005],dc[15005],dd[15005],ddt[15005];
// 桶  输入 合法的AB物品组数 权A       权B       大小为i的A,B,C,D物品数量          至i合法的C,D组数

int main部分,枚举 $t$,使 $t\lt n/9$,非常合理。
然后,枚举 $B$。(此处和原题解不同,因为本人认为这样写更好理解)
首先,考虑一个数作为 $xb$ 要满足的条件。
很简单,即

for(int b=t*2+1;b<n-t*7;b++)

这时,我们可以开一个数组 $q$,记录从 $b$ 开始,合法的AB物品组数,即 $SumA∗SumB$。
同时为了以后方便回推 $xa$,$xb$,记录每组物品中A,B物品的数量,称为 $qb$,$qa$。
最终算数量时,因为每个A对 $qa$ 个B,所以可以以B的数量作为A的权,即 $qa$ (权A)。B同理。
代码片段如下:

for(int b=t*2+1;b<n-t*7;b++)q[b]=q[b-1]+x[b-t*2]*x[b],qa[b-t*2]+=x[b],qb[b]+=x[b-t*2];

下一步,枚举C,D物品。
C物品数量为 $q*x_d$,D同理。
此时需统计合法的C,D组数,即 $ddt$。
代码片段如下:

for(int d=t*9+1;d<=n;d++){
	dd[d]+=q[d-t*7-1]*x[d-t];
	dc[d-t]+=q[d-t*7-1]*x[d];
	ddt[d-t*7-1]+=x[d]*x[d-t];
}

最后,算AB,初始化。

3.代码

先进食后人:

$b-a=2(d-c)$!别看反了

#include<bits/stdc++.h>
using namespace std;
int n,m,x[15005],f[40005],q[15005],qa[15005],qb[15005],da[15005],db[15005],dc[15005],dd[15005],ddt[15005]; 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);   
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++)cin>>f[i],x[f[i]]++;
	for(int t=1;t*9<n;t++){
		q[t*2]=0;
		for(int b=t*2+1;b<n-t*7;b++)q[b]=q[b-1]+x[b-t*2]*x[b],qa[b-t*2]+=x[b],qb[b]+=x[b-t*2];
		for(int d=t*9+1;d<=n;d++){
			dd[d]+=q[d-t*7-1]*x[d-t];
			dc[d-t]+=q[d-t*7-1]*x[d];
			ddt[d-t*7-1]+=x[d]*x[d-t];
		}
		for(int i=n-t*7-1;i>t*2;i--)ddt[i]+=ddt[i+1],da[i-t*2]+=ddt[i]*qa[i-t*2],db[i]+=ddt[i]*qb[i];
		memset(ddt,0,sizeof(ddt));
		memset(qa,0,sizeof(ddt));
		memset(qb,0,sizeof(ddt));
	}
	for(int i=1;i<=m;i++)cout<<da[f[i]]<<' '<<db[f[i]]<<' '<<dc[f[i]]<<' '<<dd[f[i]]<<'\n';
}

4.结语

首先,希望本题解对你有所帮助。
如果你对本题解有任何疑问,请评论,我会第一时间改正的QAQ
最后麻烦管理大大给过

posted @   yzc_is_SadBee  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示