[题解] LuoguP6476 [NOI Online 2 提高组]涂色游戏


https://www.luogu.com.cn/problem/P6476

估计这是窝唯一能过的题了......

建议手画几张图,窝太懒了就不画了......

讲一下考场上的思路吧(可能会有一些没用的东西)...

首先先想到一个\(lcm\)刚好是一个循环,然后只需要考虑\(lcm\)以内的就好了。

设给的两个数为\(p,q\)(默认\(p<q\)),贪心的想,窝只用考虑\(p\)的倍数是否组成连续\(k\)个同颜色的块就可以了。

那么显然对于\(q\)跳出来的一段,往里面塞\(p\),也就是对于所有\(q\)的倍数都标上蓝色,其他\(p\)的倍数都标上红色(\(0\)也标上蓝色)。

那么就变成了\(q\)跳出来的一段内最多塞了多少\(p\),刚开始的想法就是直接考虑\([0,q]\)内有多少\(p\)的倍数(不算\(0\)\(q\)),这显然是\((q-1)/p\)的。

然后按这样写就能过第一个样例了。

但是

发现第二个样例萎了......

后来想到应为按上面的方法,第一段并没有把\(0\)算上去,可以画一下\(p=2,q=11\)的图,第二段中红色的点就比第一段中的多。

也就是会有错位的部分,那么窝令最小错位能错\(g\)个位置(这样一段内红色的是最多的)

也就是\(px-qy=g\),发现\(g\)最小为\(\gcd(p,q)\),也对这一段算一下有多少红色就好了。

还有就是注意一些特判...

考场代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll gcd(ll x, ll y) { return y ? gcd(y,x%y) : x; }

inline bool chk(ll p, ll q, ll k) {
  if (p>q) swap(p,q);
  if (k == 1) return false;
  if (p == q) return true;
  ll g = gcd(p,q);
  return (q-1)/p < k && (q-1-g)/p+1 < k;
}

int main() {
//  freopen("color.in", "r", stdin);
//  freopen("color.out", "w", stdout);
  int T; for (scanf("%d", &T); T; T--) {
    ll p, q, k; scanf("%lld%lld%lld", &p, &q, &k);
    puts(chk(p,q,k) ? "Yes" : "No");
  }
  return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM