题解 CF200E 【Tractor College】

· · 题解

拖拉机学院

这不就是南翔

勘误:

输出格式那里应该是“一行三个数”,我翻译的时候打太快没看见

没错,译者写题解

思路

首先看题,似乎毫无头绪,但时间限制给了我们思路:

果断枚举

c_{3}, c_{4}, c_{5} 都是常数,考虑枚举 k

这样,我们就可以由 $c_{3}k_{3}+c_{4}k_{4}+c_{5}k_{5}=s$ 以$O(1)$复杂度算出 $k_{5}

枚举出的 k_{3}, k_{4}, k_{5} 若满足 c_{3}k_{3}+c_{4}k_{4}+c_{5}k_{5}=s,就是一组合法的解,算出其 f(k_{3}, k_{4}, k_{5}) 的值更新即可

细节

0开始枚举结果过于复杂,我们不妨从最大值入手

题目中说 0 \leqslant k_{3} \leqslant k_{4} \leqslant k_5,且 c_{3}k_{3}+c_{4}k_{4}+c_{5}k_{5}=s ,所以 k_{4}, k_{5}k_{3} 取最大值的“阻碍”

那么没有人拿4分或5分的时候 k_{3} 就能取到最大值了【滑稽】

当然,这种情况不符合题意,但我们讨论的是理论最大值,不用担心

接下来 k_{4} 的最大值做法类似,假装没有人拿5

总结

代码难度不大,但思路有点难想,目测 提高+/省选-

总复杂度应该不会超过 O(s^2) (蒟蒻不会算……)

------------ ### 代码 抄题解后果自负【滑稽】 ```cpp #include<con> #define INF 2139062143 using namespace std; int n,s; int c3,c4,c5; int min_f=INF; int ans1,ans2,ans3; int k; inline int f(int k3,int k4,int k5){ return abs(c3*k3-c4*k4)+abs(c4*k4-c5*k5); }//算f inline int read(){ char ch=getchar(); int ans=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){ ans=ans*10+ch-'0'; ch=getchar(); } return ans; }//快读 int main(){ n=read();s=read(); for(int i=1;i<=n;i++){ k=read();//这个k下面还用来算k5,也是物尽其用【滑稽】 if(k==3)c3++; else if(k==4)c4++; else if(k==5)c5++; } for(int i=s/n;i>=0;i--){//从最大值开始枚举 for(int j=(s-c3*i)/(n-c3);j>=i;j--){//k4>=k3, 所以 j>=i k=(s-c3*i-c4*j)/c5; if(i*c3+j*c4+k*c5==s&&f(i,j,k)<min_f){//如果符合题意且可以更新 min_f=f(i,j,k); ans1=i; ans2=j; ans3=k;//更新 } } } if(min_f!=INF)printf("%d %d %d",ans1,ans2,ans3); else printf("-1");//无解即根本没更新过 } ```