Educational Codeforces Round 164 (Rated for Div. 2) D

因为理解错了题目导致我没错出来。我理解为有两个人取球,每个人每次都是取一组,也就是一组的球必须要放在一个人手里。。因为我之前做的一个背包是这个样子的。这就导致了,我认为每次转移所需要的信息是比实际要的多很多的,直接导致我没法设计一个正常的dp。
然后炸了。。。

好烦。。。完全可以上1800的一场,结果因为这种题意理解的问题寄了。
掉了25分。

这个其实也是因为之前做到的题目导致的吧。。给我的思维带来了一个奇妙的导向。很蠢。
以后其实遇到了这种完全没思路,但是大家又都会做的时候,可以把思维的每一个环节都仔细考虑一下,是不是题读错了之类的错。。。
太傻了。

其实就是背包,然后随便推推就没了。思路就是之前的那些,找到一个东西,固定它能够使得代价可统计。就没了。

然后因为取模的原因死在了test13,又因为下取整的原因死在了test5,这个下取整一定要带括号。。。不然会变化的。

具体做法就是先让a[i]从小到大排序,设f[i][j]表示前i类物品,任意取,最终数量有j个的方案数。
然后转移就是f[i][j]=f[i1][j]+f[i][ja[i]](0jtot)tot
然后我们从1枚举到n,枚举这次把哪一类小球产生的价值记入答案,因为我们的a[i]是从小到大排序的,所有每次加入的肯定都是当前这个方案里面数量最多的小球种类。
我们考虑怎么统计答案(其实这个应该是要先考虑,然后才有的这个做法),对于每一个种类的小球,我们枚举前面已经选取的多少个小球,设这个数字为sum,而a[i]就是小球数量最多的种类的数量,当a[i]sum的时候,产生的代价就是a[i]×,而当a[i]<sum的时候,答案其实就是(a[i]+sum)/2×,可以证明,如果答案不是这个,就说明a[i]前,也就是a[1...(i1)]里面有比a[i]更大数字,而我们排过序了,这个是不可能的。所以是一定成立的。那其实就是一个计数背包。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read() {
	char c=getchar();ll a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
ll n,a[5001],f[5001][5001];
const ll Mod=998244353;
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ll T=read();
//	while(T--)
//	{
	n=read();ll all=0;ll ans=0;
	for(ll i=1;i<=n;i++)a[i]=read(),all+=a[i];
	sort(a+1,a+1+n);
	f[0][0]=1;
	for(ll i=1;i<=n;i++)
	{
		for(ll j=0;j<=all;j++)
		{
			f[i][j]=(f[i-1][j]);
			if(j>=a[i])f[i][j]+=f[i-1][j-a[i]];
			f[i][j]%=Mod;
		}
	}
	for(ll i=1;i<=n;i++)
	{
		for(ll j=0;j<=all;j++)
		{
			if(f[i-1][j]!=0)
			{
				if(j<=a[i])
				{
					ans+=a[i]*f[i-1][j];
				}
				else
				{
					ans+=f[i-1][j]*((j+a[i]+1)/2);
				}
				ans%=Mod;
			}
		}
	}
	cout<<ans%Mod<<endl;
//	}
	return 0;
}
/*
5
6 6 19 25 44


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