Skip to main content
Original330 words2 min

题解:P8948 [YsOI2022] NOIp 和省选

Summary

两场考试满分 400、600,第 i 人的标准分为一千乘以两场得分率之和再四舍五入,已知所有标准分(第一人为 2000),构造任意一组合法原始分。两场最高分由你的输出决定,取第一人两场满分并令最高分为 200、500,则标准分恰等于 5 倍首场加 2 倍次场,舍入不再起作用。于是对每人解方程 5a+2b=c 并满足取值范围,由奇偶性与上界确定 a、再算出 b。时间复杂度 O(n)。

题意简述​

两场考试满分 400400、600600。设两场最高分为 A,BA,B,第 ii 人标准得分 ci=round⁡(1000(aiA+biB))c_i=\operatorname{round}\left(1000\left(\frac{a_i}{A}+\frac{b_i}{B}\right)\right)。已知 nn 与所有 cic_i(c1=2000c_1=2000,其余在 [10,1990][10,1990]),构造任意一组合法原始分 ai∈[0,400]a_i\in[0,400]、bi∈[0,600]b_i\in[0,600]。

解题思路​

AA、BB 由你的输出决定,等于各自那列的最大值。第 11 人 c1=2000c_1=2000,两场都满,故 a1=Aa_1=A、b1=Bb_1=B,可自行指定 AA、BB。

关键是消掉四舍五入。取 A=200A=200、B=500B=500,则:

ci=1000(ai200+bi500)=5ai+2bic_i=1000\left(\frac{a_i}{200}+\frac{b_i}{500}\right)=5a_i+2b_i

右端恒为整数,舍入不再起作用,只需解方程 5ai+2bi=ci5a_i+2b_i=c_i,且 ai∈[0,200]a_i\in[0,200]、bi∈[0,500]b_i\in[0,500]。

由 bi=ci−5ai2b_i=\frac{c_i-5a_i}{2},要求 ci−5aic_i-5a_i 为非负偶数且不超过 10001000。两个条件确定 aia_i:

  1. 方程两边对 22 取模,得 ai≡ci(mod2)a_i\equiv c_i\pmod 2。
  2. 由 bi≤500b_i\le 500 得 ai≥ci−10005a_i\ge\frac{c_i-1000}{5}。

取满足下界的最小整数 ai=max⁡(0,⌈ci−10005⌉)a_i=\max\left(0,\left\lceil\frac{c_i-1000}{5}\right\rceil\right),整数写法为 max⁡(0,⌊(ci−996)/5⌋)\max\left(0,\lfloor(c_i-996)/5\rfloor\right)。若其奇偶与 cic_i 不符则加 11,再令 bi=ci−5ai2b_i=\frac{c_i-5a_i}{2}。

可验证如此得到的 ai≤198a_i\le 198、bi≤500b_i\le 500,故第 11 人的 a1=200a_1=200、b1=500b_1=500 恰为两列最大值,A=200A=200、B=500B=500 成立,构造自洽。

时间复杂度为 O(n)O(n)。

参考代码​

279 Bcpp
#include <bits/stdc++.h>
using namespace std;

int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,c;
cin>>n>>c;
cout<<"200 500\n";
for(int i=2;i<=n;i++)
{
cin>>c;
int a=max(0,(c-996)/5);
if((a^c)&1)a++;
cout<<a<<' '<<(c-5*a)/2<<'\n';
}
return 0;
}