[題解] 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