题目描述
小z热衷于数学。
今天数学课的内容是解不等式:L<=S*x<=R 。小z心想这也太简单了,不禁陷入了深深的思考:假如已知L,R,S,M ,满足L<=(S*x) mod M<=R 的最小正整数x该怎么求呢?
输入
包含多组数据。
第一行包含一个整数T,表示数据组数,接下来是T行,每行为四个正整数M,S,L,R 。
输出
对于每组数据,输出满足要求的x值,若不存在,输出-1 。
样例输入
1
5 4 2 3
样例输出
2
提示
30%的数据中保证有解并且答案小于等于10^6;
另外20%的数据中保证L=R;
100%的数据中T<=100,M,S,L,R<=10^9。
直接枚举答案便可以得到的分数。
的部分分用扩展欧几里得可以解决,这里不做过多阐述。
对于的做法,首先我们排除特殊情况,不妨设,0<=l<=r,0<=s<=m。
显然若存在一个的倍数满足l<=s*x<=r,那么此时的答案就是x。
若不存在,我们不妨将约束式改写成代数式l<=s*x-m*y<=r。进一步改写成以为y主元,即-r<=m*y-s*x<=-l,再把它还原为取模的形式:(-r mod s)<=m*y mod s<=(-l mod s)。若能求出最小的满足上式的y值,则可以求出唯一满足上式的x值(因为区间中没有s的倍数)。
所以我们只需要将读入的四个数标准化,判断是否存在简单解以及判断无解,假如需要的话递归调用函数,直至问题解决。
具体实现可以参考标程。
var
t,m,s,l,r:int64;
function dfs(m,s,l,r:int64):int64;
var
x,k,i:int64;
begin
if l=0 then exit(0);
if l>=m then exit(-1);
if l>r then exit(-1);
if s mod m=0 then exit(-1);
s:=s mod m;
i:=(l-1)div s +1;
if i*s<=r then exit(i);
k:=dfs(s,m,(-r mod s+s) mod s,(-l mod s+s) mod s);
if k=-1 then exit(k);
x:=(r+m*k) div s;
if (s*x-m*k)>=l then exit((x mod m+m) mod m) else exit(-1);
end;
begin
readln(t);
while t>0 do
begin
t:=t-1;
readln(m,s,l,r);
if r>=m then r:=m-1;
writeln(dfs(m,s,l,r));
end;
end.