Unordered_OIer
2020-11-28 20:27:16
构造两个长度为
先记
首先,我们先考虑满足一共有
为了简化操作,我们直接让
于是我们先让
然后,我们定义
当第
于是剩下的就直接取
至此,数列
以上仅为有解情况,还需要考虑无解情况。
无解情况就是
用式子表示即为
总的复杂度为
代码因为加了注释比较长,文末有更简洁的代码。
// namespace Solution
const ll N = 100005;
ll x[N], y[N];
void check() { // check
ll sum = 0, cnt = 0;
bool flag = 1;
for (ll i = 1; i <= n; i++)
sum += x[i], flag &= ((x[i] + y[i]) == m && (x[i] >= 0 && y[i] >= 0)), cnt += (x[i] == q); // recount
if (sum != k || !flag || cnt != p) { // review
puts("NO");
exit(0);
}
}
int main() {
ll n = read(), m = read(), k = read(), p = read(); // read
ll q = min(m, k / p); // 最大值
if (k - q * p > (n - p) * (q - 1)) // 如果 分配完所有最大值 后 剩余的数分配给剩余的人 每个人 q-1 仍会有剩余
return puts("NO"), 0; // 无解
// Case 1 - p max
for (ll i = 1; i <= p; i++) // 这些 xi 都取最大值
x[i] = q, y[i] = m - q;
// Case 2 - n-p less
bool fflag = 1; // 用于记录是否剩余还可以分出 q-1
ll rest = k - q * p; // rest 记录剩余的个数
for (ll i = p + 1; i <= n; i++) {
// Subcase 1 - q-1 ok
if (fflag == true && rest >= q - 1) // judge
x[i] = q - 1, rest -= q - 1; // 赋值,且剩余减去 q-1
// Subcase 2 - rest == 0 too little
else if (rest <= 0) // judge
x[i] = 0; // 0
// Subcase 3 - still have , but not enough
else
x[i] = rest, rest = 0, fflag = 0; // get all the rest
y[i] = m - x[i]; // set y
}
// namespace Output
puts("YES");
// check();
for (ll i = 1; i <= n; i++)
write(x[i]), putchar(' '), write_endl(y[i]); // output
return 0;
}
更简洁一点的代码:
ll n=read(),m=read(),k=read(),p=read();
ll q=min(m,k/p);
if(k-q*p>(n-p)*(q-1))return puts("NO"),0;
for(ll i=1;i<=p;i++)x[i]=q,y[i]=m-q;
bool ff=1;
ll rs=k-q*p;
for(ll i=p+1;i<=n;i++){
if(ff==true&&rs>=q-1)x[i]=q-1,rs-=q-1;
else if(rs==0)x[i]=0;
else x[i]=rs,rs=0,ff=0;
y[i]=m-x[i];
}
puts("YES");
for(ll i=1;i<=n;i++)write(x[i]),putchar(' '),write_endl(y[i]);
个人觉得算是半道模拟题
最后,祝洛谷月赛越办越好!
完结撒花~顺便求赞