【BZOJ1477】青蛙的约会

【题目链接】

【前置技能】

  • 逆元

【题解】

  • 题目要求的是最小的非负整数 t t t,使得 x + t ∗ m ≡ y + t ∗ n   ( m o d   L ) x+t*m\equiv y+t*n~(mod~L) x+tmy+tn (mod L),移项,合并同类项,得到 t ∗ ( n − m ) ≡ x − y   ( m o d   L ) t*(n-m)\equiv x-y~(mod~L) t(nm)xy (mod L),这里不妨设 n ≥ m n\geq m nm
  • 发现这其实就是一个线性同余方程。令 d = g c d ( n − m , L ) d = gcd(n-m,L) d=gcd(nm,L),那么有解的条件是 d   ∣   ( x − y ) d~|~(x-y) d  (xy)。解得 t ≡ ( ( n − m ) / d ) − 1 ∗ ( x − y ) / d   ( m o d   ( L / d ) ) t\equiv ((n-m)/d)^{-1}*(x-y)/d~(mod~(L/d)) t((nm)/d)1(xy)/d (mod (L/d)),输出一个最小非负整数解即可。
  • 时间复杂度 O ( l o g N ) O(logN) O(logN)

【代码】

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL  long long
using namespace std;
LL x, y, m, n, l, a, b;
 
template <typename T> void chkmin(T &x, T y){x = min(x, y);}
template <typename T> void chkmax(T &x, T y){x = max(x, y);}
template <typename T> void read(T &x){
    x = 0; int f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}
 
LL gcd(LL a, LL b){
    if (a == 0 || b == 0) return a + b;
    return gcd(b, a % b);
}
 
void exgcd(LL a, LL b, LL &x, LL &y){
    if (b == 0) {x = 1, y = 0; return;}
    LL q = a / b, r = a % b;
    exgcd(b, r, y, x);
    y -= x * q;
}
 
int main(){
    read(x), read(y), read(m), read(n), read(l);
    if (n < m) {swap(n, m); swap(x, y);}
    LL d = gcd(l, n - m);
    if ((x - y) % d) printf("Impossible\n");
    else {
        LL a = n - m, b = x - y;
        a /= d, b /= d, l /= d;
        exgcd(a, l, x, y);
        LL ans = (b % l) * (x % l) % l;
        if (ans < 0) ans += l;
        printf("%lld\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值