Description
小z热衷于数学。
今天数学课的内容是解不等式:L<=S*x<=R。小z心想这也太简单了,不禁陷入了深深的思考:假如已知L、R、S、M,满足L<=(S*x)mod M<=R的最小正整数x该怎么求呢?
Input
第一行包含一个整数T,表示数据组数,接下来是T行,每行为四个正整数M、S、L、R。
Output
对于每组数据,输出满足要求的x值,若不存在,输出-1。
Sample Input
1
5 4 2 3
Sample Output
2
Data Constraint
30%的数据中保证有解并且答案小于等于10^6;
另外20%的数据中保证L=R;
100%的数据中T<=100,M、S、L、R<=10^9。
小结
考试的时候我就一直再解这个不等式,结果发现行不通,因为有个mod,搞得我,多狼狈。
其实正解是这样的,首先,我们看看这个不等式:
①L
≤
Sx mod m
≤
R.
我们可以设成:
②L
≤
Sx-my
≤
R.
于是乘上-1就变成:
③-R
≤
my-Sx
≤
-L.
于是同理就可以用变成
④-R
≤
my mod S
≤
-L。
于是我们就可以用dfs实现这个过程,我们带进去m,s,l,r。我们知道,如果l>r,那就没意义,-1;如果l
≥
m,也没意义,-1;如果s%m=0,也没意义,因为这样就不会有余数了,所以-1。如果l=0,就是0;
然后就可以判断了。首先,s=s%m,这样①式就可以变成x=(l-1)/s+1,于是判断是否合法,如果合法就返回。从④推出y要等于dfs(m,s,-r,-l);的结果,对吧,但是防止-r,-l是负数,就要变成dfs(m,s,(-r%s+s)%s,(-l%s+s)%s);这样结果不会变,但是很好的防止了负数的出现。得到y了,我们看看y如果=-1,那么就不合法,-1;然后,我们由②式推出,x=(r+m*y)/s;最后判断一下如果这个数合法,那么就返回,否则-1。
#include<cstdio>
#include<iostream>
using namespace std;
long long t,m,s,l,r;
long long dfs(long long m,long long s,long long l,long long r)
{
if (l==0) return 0;
if (l>r) return -1;
if (l>=m) return -1;
if (s%m==0) return -1;
s%=m;
long long x=(l-1)/s+1;
if (s*x<=r) return x;
long long y=dfs(s,m,(-r%s+s)%s,(-l%s+s)%s);
if (y==-1) return -1;
x=(r+m*y)/s;
if (s*x-m*y>=l) return (x%m+m)%m;
return -1;
}
int main()
{
freopen("solve.in","r",stdin);
freopen("solve.out","w",stdout);
scanf("%lld",&t);
for (int i=1;i<=t;++i)
{
scanf("%lld%lld%lld%lld",&m,&s,&l,&r);
if (r>=m) r=m-1;
printf("%lld\n",dfs(m,s,l,r));
}
}