[cf10E]Greedy Change

对于$w$的表示方案,可以用序列描述,即$x_{i}$表示第$i$种货币的数量

贪心策略得到的方案即是(对应序列)字典序最大的方案,并定义最优策略得到的方案为在最小化货币总数的基础上,(对应序列)字典序最大的方案

记$g_{w}$和$f_{w}$分别为贪心和最优策略下$w$的表示方案,问题即求最小的$w$满足$sum_{i=1}^{n}g_{w,i}>sum_{i=1}^{n}f_{w,i}$

(以下方案比较均按照字典序,性质1-4均比较显然,可以简单思考后跳过证明)

性质1:$forall w_{1}<w_{2},g_{w_{1}}<g_{w_{2}}$

反证法,若$g_{w_{1}}ge g_{w_{2}}$,构造$g'$为在$g_{w_{1}}$的方案再选择$w_{2}-w_{1}$个$a_{n}=1$,显然$g'$也是$w_{2}$的一种表示方案且$g'>g_{w_{1}}ge g_{w_{2}}$,与贪心策略(字典序的最大性)矛盾

性质2:记答案为$s$,则$forall 0le w<s,g_{w}=f_{w}$

根据最优策略和$s$的最小性,有$forall 0le w<s,sum_{i=1}^{n}g_{w,i}=sum_{i=1}^{n}f_{w,i}$,即$g_{w}$取到了货币总数的最小值,那么根据最优策略(字典序的最大性)知$g_{w}le f_{w}$

另一方面,根据贪心策略知$g_{w}ge f_{w}$,结合两者即得证

性质3:若$g/f_{w,i} e 0$,则$g/f_{w-a_{i}}$必然是$g/f_{w}$的方案再去掉一个$a_{i}$

(不妨以$g$为例,$f$可以类似证明)

构造$g'$为$g_{w}$的方案再去掉一个$a_{i}$,若$g' e g_{w-a_{i}}$,根据贪心策略知$g'<g_{w-a_{i}}$

再在两者的方案中同时选择一个$a_{i}$,前者显然变为$g_{w}$,又与贪心策略矛盾

性质4:$forall 1le ile n$,$g_{s,i}$和$f_{s,i}$不同时非0

反证法,若存在$i$使得$g_{s,i},f_{s,i}$均非0,任取其中一个$i$

根据性质2,有$g_{s-a_{i}}=f_{s-a_{i}}$,进而$sum_{i=1}^{n}g_{s-a_{i},i}=sum_{i=1}^{n}f_{s-a_{i},i}$

又根据性质3,有$sum_{i=1}^{n}g/f_{s-a_{i},i}=sum_{i=1}^{n}g/f_{s,i}-1$

其中左式两者相等,而右式两者不等(根据$s$的定义),矛盾

令$x$和$y$分别为$f_{s}$第一个和最后一个非0的位置(显然存在),则有以下性质——

性质5:$xge 2,sge a_{x-1}$且$s-a_{y}<a_{x-1}$

关于前者(指$xge 2,sge a_{x-1}$),若不满足显然$g_{s,x} e 0$,与性质4矛盾

关于后者,根据性质2,有$f_{s-a_{y}}=g_{s-a_{y}}$,而前者是$f_{s}$的方案中再去掉一个$a_{y}$,那么$1,2,...,x-1$也均为0,而如果$s-a_{y}ge a_{x-1}$显然后者$1,2,...,x-1$中存在非0位,矛盾

结论:$forall xle i<y,f_{s,i}=g_{a_{x-1}-1,i}$且$f_{s,y}=g_{a_{x-1}-1,y}+1$

根据性质1和2,有$f_{s-a_{x}}=g_{s-a_{x}}>g_{a_{x-1}-1-a_{x}}$

根据性质3,两者分别是$f_{s}$和$g_{a_{x-1}-1}$的方案再去掉一个$a_{x}$(注意$a_{x-1}-1ge a_{x}$),进而在两者的方案中同时选择一个$a_{x}$,即得到$f_{s}>g_{a_{x-1}-1}$

另一方面,同样根据性质1和2,有$f_{s-a_{y}}=g_{s-a_{y}}le g_{a_{x-1}-1}<f_{s}$

同样根据性质3,$f_{s-a_{y}}$是$f_{s}$的方案中再去掉一个$a_{y}$,而字典序因此变化,显然结论成立

根据此结论,显然$f_{w}$被$x,y$唯一确定(其余位置均为0),枚举$x,y$并求出$f_{w}$,进而求出$w$和$g_{w}$并比较两者的货币数即可(注意这里并不保证求出的$f_{w}$是最优的,但在答案处是最优的,且比答案小的最优方案都不比$g_{w}$优,该方案显然也不能比$g_{w}$优)

贪心策略的方案容易$o(n)$求出,总复杂度为$o(n^{3})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 405
 4 int n,ans,a[N],f[N];
 5 void check(){
 6     int cnt=0,sum=0;
 7     for(int i=1;i<=n;i++)cnt+=f[i],sum+=f[i]*a[i];
 8     for(int i=1,s=sum;i<=n;i++)cnt-=s/a[i],s%=a[i];
 9     if (cnt<0)ans=min(ans,sum);
10 }
11 int main(){
12     scanf("%d",&n);
13     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
14     ans=2e9;
15     for(int i=1;i<=n;i++){
16         memset(f,0,sizeof(f));
17         for(int j=i,s=a[i-1]-1;j<=n;j++){
18             f[j]=s/a[j],s%=a[j];
19             f[j]++,check(),f[j]--;
20         }
21     }
22     if (ans==2e9)ans=-1;
23     printf("%d
",ans);
24     return 0;
25 } 
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/15513480.html