題目地址
題目大意
現有\(10^{100}\)塊木板需要塗漆,第x塊如果是x是a的倍數,則塗一種顏色,是b的倍數,則塗另一種顏色。如果既是a又是b的倍數,那么兩種顏色都可以塗;如果連續有k塊板的顏色是一樣的,則輸出REBEL,否則輸出OBEY。問是否能避免被處死。我們肯定優先使不被處死。
Solution
一周前被這個題目吊打,一周后吊打這個題目
令 \(a < b\)。b染的色就會是 \(1b,2b,...,kb\) 這些格子,而最長的顏色段應該是由 \(a\) 的倍數組成的,而且一定是在兩個 \(b\) 的倍數之間。兩個 \(b\) 的倍數間有 \(b-1\) 個格子,是固定的,想要讓這中間 \(a\) 的倍數盡可能多,就要讓段 \(a\) 的倍數中的第一個數離上一個 \(b\) 的倍數最近。假設這個距離為 \(c\),那么就相當於滿足方程:
\[ax+by=c \]
(這不就是擴展歐幾里得嗎!!!)別激動,我們只要考慮當這個方程有解時,\(c\) 可以取的最小的正整數是多少。所以這是裴蜀定理。因為要使這個方程有解,就要滿足 \(gcd(a,b)|c\) 所以 \(c\) 最小取 \(gcd(a,b)\)
處理一下細節,最長的連續的顏色就會是 (b-gcd(a,b)-1)/a)+1
(先單獨算上 \(gcd(a,b)\) 這個位置的這個 \(1\),后面這段每 \(a\) 個數就有一個 \(1\))
Code
Talk is cheap.Show me the code.
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x=0,f=1; char ch=getchar();
while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
return x * f;
}
int a,b,K;
int gcd(int a,int b) {
return (b==0?a:gcd(b,a%b));
}
void work() {
a = read(), b = read(), K = read();
if(a>b) swap(a,b);
printf("%s\n",(((b-gcd(a,b)-1)/a)+1<K?"OBEY":"REBEL"));
}
int main()
{
int T = read();
while(T--) work();
return 0;
}
Summary
這道題好水呀,注意細節就OK啦