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

来源:互联网 发布:mysql删除数据库delect 编辑:程序博客网 时间:2024/05/29 06:42

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,搞得我,多狼狈。
其实正解是这样的,首先,我们看看这个不等式:
①LSx mod mR.
我们可以设成:
②LSx-myR.
于是乘上-1就变成:
③-Rmy-Sx-L.
于是同理就可以用变成
④-Rmy mod S-L。
于是我们就可以用dfs实现这个过程,我们带进去m,s,l,r。我们知道,如果l>r,那就没意义,-1;如果lm,也没意义,-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));    }}
原创粉丝点击