题目链接
CF 1260C是原题,数据范围略有差别。
题意简述
有两个数a≤b,给出k,问是否存在mb<na<(n+1)a<⋯(n+k−1)<(m+1)b,(m+1)b<1020,m,n∈N,n≥1。存在输出“NO”,不存在输出“YES”(由于转换了求的东西所以存在和不存在与原题输出相反)。
题解
先说一下为什么这么化简题意。原题中的p1,p2这里用a,b表示。不妨设a≤b,则染色的情况必定为a⋯aba⋯aba⋯的情形。可以发现,相当于是b在截断a的连续染色。而为了实现原题中不超过k个连续的愿望,lcm(a,b)显然要染成b去防止a的延伸。接下来只需要看是否在1020−1的范围内,每个b之间间隔的a的数量都小于k。当然,首先要特判k=1的情况。
接下来讲一下我的解题思路。一开始是想至少搞一个下界出来,即:假设每个b之间夹的a的数量最多为c,则c≥⌊ab−1⌋,也就是一开始0∼b中存在的a的数量。仔细想想,由于b−1=⌊ab−1⌋×a+r,0≤r<a,如果想在两个b地倍数之间的a开头往前或结尾往后扎扎实实地再塞进一个a是不可能的,想要再添加只有可能是存在一个数λ,mb<λ<mb+r。这样好像讲的有点乱,看图明白一点:
截取线段和什么类似?取模!若λ存在,则不可避免的最多颜色连续数为⌊ab−1⌋+1,不然,则为⌊ab−1⌋。即为判定ax≡t(mod b)(0≤t<r)是否有解。进一步的,判定ax+by=t是否有解。又由裴蜀定理知,该方程有解的充要条件为gcd(a,b)∣t。且r可以取遍0∼r−1的整数,所以只需判断r和gcd(a,b)的大小关系。如此一来,只需将最多颜色连续数和k进行比较,若k比较大则有解,否则无解。本题就得到了解决。特殊地,当a∣b时r=0,此时是可以不让b染成a的,代入发现同样可以通过比较r与gcd(a,b)的大小关系获得正确答案。
等等,我们还有个范围问题!怎么确定如此找到的(m+1)b是否小于1020呢?设d=gcd(a,b),由于ax+by=t的解集与dax+dby=dt相同,不妨先设a⊥b。
先证明一个引理:当a⊥b时,{0,a,2a,⋯,(b−1)a}构成b的完全剩余系。
首先,{0,a,2a,⋯,(b−1)a}和{0,1,2,⋯,b−1}在元素个数上相同。下用反证法证明原集合中元素对b取模结果两两不同即可。
若ax≡ay(mod b)(0≤x,y<p,x=y),且a⊥b,则x≡y(mod b)。进一步的,由于0≤x,y<p,则x=y,得出矛盾。
证毕。
这一步是想说明,只要有解,解的范围就在[0,b/d−1]中。而mb<ax+t≤a(b−1)+a=ab,(m+1)b<ab+b≤1018+109<1020。
这回是真的结束了。
代码:
#include <cstdio>
#include <cctype>
char ans[2][10]={"NO\n", "YES\n"};
int gcd(int a,int b) {return b?gcd(b, a%b):a;}
int read()
{
int res=0;
char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch))
res=res*10+ch-'0',ch=getchar();
return res;
}
int main()
{
int T=read();
while(T--)
{
int a=read(),b=read(),k=read();
if (a>b)
a^=b^=a^=b;
if (k==1)
printf("%s",ans[0]);
else
{
int d=gcd(a, b),r=b%a;
int s=(b-1)/a+(r>d);
printf("%s",ans[s<k]);
}
}
return 0;
}