1 条题解
-
0
自动搬运
来自洛谷,原作者为

Unordered_OIer
**搬运于
2025-08-24 22:26:42,当前版本为作者最后更新于2020-11-28 20:27:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P7107 题解
题意
构造两个长度为 的数列 和 ,使得:
- 一共有且仅有 个 使得
题解
先记
首先,我们先考虑满足一共有 个 使得 这个条件,由于一共最多只能有 个这样的最大值,于是我们可以得到这个最大值 ,再取大,就会导致 ,不满足题意。
为了简化操作,我们直接让 。
于是我们先让 。
然后,我们定义 ,表示剩余有标记的纸团的个数,又要保证 ,所以我们考虑在一定有解且 的情况下,剩下的 取 最合适。
当第 个人取 时, ,那么直接把剩下所有的 都给这个 ,至此,所有有记号的纸条都已经分发完毕。
于是剩下的就直接取 ,即 。
至此,数列 和 就构造完毕了,而且复杂度也是 的。
以上仅为有解情况,还需要考虑无解情况。
无解情况就是 个 分配完后所剩余的 分配给剩下的 个人每人 后仍有剩余,则我们是找不到这样的 的。
用式子表示即为 。
总的复杂度为 ,可以 。
Code
代码因为加了注释比较长,文末有更简洁的代码。
// 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]);后记
个人觉得算是半道模拟题
最后,祝洛谷月赛越办越好!
完结撒花~顺便求赞
- 1
信息
- ID
- 6020
- 时间
- 1000ms
- 内存
- 250MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者