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

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

(File IO): input:solve.in output:solve.out
Time Limits: 1000 ms Memory Limits: 262144 KB

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。

题解

这道题网上有很多一样的题解,看了好久才明白,其实这题就是用类欧思想

题目所给的式子是

L(Sx) mod MR

显然,若存在一个 x 满足LSxR,那么答案就是 x

如果不存在,转化题目那条式子

L(Sx) mod MR

LSxMyR

RMySxL

(R mod S)(My) mod S(L mod S)

若能求出 y ,那么自然x就知道了,因为区间 [L,R] 中没有 x 的倍数

然后我们就可以用类欧几里得来求解了
之所以叫类欧,是因为欧几里得算法是用gcd(b,a mod b)来求 gcd(a,b)

这题也类似
定义 x=dfs(M,S,L,R) ,那么 y=dfs(M,S,R mod S+S,L mod S+S)
于是
x=R+MyS

边界条件好多,具体可以看代码

代码

#include<cstdio>

long long dfs(long m,long s,long l,long r)
{   long long x,y;
    if(l==0)return 0;
    if(l>=m||l>r||s%m==0)return -1;
    s%=m;
    x=((l-1)/s)+1;
    if(x*s<=r)
        return x;
    y=dfs(s,m,(-r)%s+s,(-l)%s+s);
    if(y==-1)return -1;
    x=(r+m*y)/s;
    if(s*x-m*y>=l)return (x%m+m)%m;
    else return -1;
}

int main()
{   long tot,m,s,l,r;
    freopen("solve.in","r",stdin);
    freopen("solve.out","w",stdout);
    scanf("%ld",&tot);
    while(tot--){
        scanf("%ld%ld%ld%ld",&m,&s,&l,&r);
        if(r>=m)r=m-1;
        printf("%lld\n",dfs(m,s,l,r));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值