CF10E Greedy Change 题解

http://codeforces.com/problemset/problem/10/E

题意

给出货币系统 {cn} 满足 c1>c2>>cn=1,请找到最小的 x 使贪心算法需要的货币数目比最优解多。

贪心算法:每次取最大的不超过 x 的货币。

1n400,1ci109

题解

x 的货币系统表示记作向量 V,即 VC=x

令向量 M(x) 为表示 x 字典序最大的最优解,G(x) 为贪心解(是字典序最大的表示)。

这样限制可以直接比较两个向量。开始推性质(下面的比较都是字典序):

  • x<y,M(x)<M(y)

  • M 的子集是最优的表示,G 的子集是贪心表示。

这些都由定义易得。

定义 s 为最小的解,这样取一个子集之后 M,G 是相等的,可以找一些必要条件:

  • M(s),G(s) 非零位无交。

如果 M,G 的第 i 位均大于 0sci 是比 s 更优的解,矛盾。

i,jM(s) 的最低和最高非零位。

  • G(scj)i1 位为 0

M(s)i1 位为 0 M(scj)i1 位为 0 G(scj)i1 位为 0

推论:scj<ci1

  • G(s) 在前 i1 位有非零位。

G(s)i 位一定是 0,如果前 i1 位也全部是 0,那么字典序就小于 M(s) 了,与定义矛盾。

推论:sci1

现在整理一下限制,因为 ci 的数量不多,想要建立和 M(s) 的关系:

sci1ci11ci<sciG(ci11ci)<G(sci)=M(sci)

发现把向量第 i 位加 1 仍是符合定义的。

对于 G 考虑贪心过程是显然的。

对于 MM(sci)M(s) 的子集,至少需要再某一位加 1,必然是第 i 位。

于是得到 G(ci11)<M(s)

从另一个限制出发:

scjci11M(scj)=G(scj)G(ci11)

本来 M(s) 字典序大于 G(ci1),第 j 位减 1 后就小于等于了。

首先它们 j 位之前相等。由于 M(s)j 位之后都是 0 ,所以 M(s)j 位恰好为 G(ci1)j 为加 1

现在可以枚举 i,jO(n) check,时间复杂度 O(n3)

代码:

#include <bits/stdc++.h>
using namespace std;
const int inf=2e9;
int main(){
	int n,ans=inf;
	scanf("%d",&n);
	vector<int> c(n);
	for(int&x:c) scanf("%d",&x);
	auto val=[&](int x){
		int res=0;
		for(int v:c) res+=x/v,x%=v;
		return res;
	};
	for(int i=1;i<n;i++){
		int s=c[i-1]-1,x=s,m=0;
		for(int j=i;j<n;j++){
			m+=x/c[j];x%=c[j];
			if(m+1<val(s-x+c[j])) ans=min(ans,s-x+c[j]);
		}
	}
	printf("%d\n",ans==inf?-1:ans);
	return 0;
}
posted @   shrtcl  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
历史上的今天:
2021-11-02 CF1246E To Make 1 题解
点击右上角即可分享
微信分享提示