您的位置:首页 > 其它

【NOIP2013模拟11.7A组】不等式(solve)

2017-07-15 21:05 288 查看

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));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: