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

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));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值