加载中...

同余方程

x和y的最大公约数是d
(x,y)=d
转化成方程
ax+by=d
参数x和y相关的表达式 x y正负不管
x=x0+kb/d (对方的那坨来加的)
y=y0-k
a/d

//拓展欧几里得
int exgcd(int a, int b, int &x, int &y)//ax=d%(mod b) x和y是ax+by=d 方程的一组可行解  返回值是最大公约数(最后一层的a)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }

    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;

    return d;
}

同余方程 求 ax=1(mod d) 的x的整数解 这里最大公约数就是1 ax+yd=1

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

int exgcd(int a, int b, int &x, int &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }

    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;

    return d;
}

int main()
{
    int a, b;
    cin >> a >> b;

    int x, y;
    exgcd(a, b, x, y);

    cout << (x % b + b) % b << endl;

    return 0;
}


青蛙约会 围着一圈 a在a点一次能跑m米,b在b点一次跑n米 一圈是L 求x跑了多少秒追上b

https://www.acwing.com/activity/content/problem/content/1753/
a:青蛙a的起点
b:青蛙b的起点
m:青蛙a一次能跳多远
n:青蛙b一次能跳多远
L:一圈的距离
(b-a):a要追b多少米
(m-n):每跳一次,a能追b多少米

x是总共跳了多少次
y是a追b不一定会在一圈内追完,而是追了y圈
(m - n)x = b - a + yL
(m - n)x - yL = b - a
——————— — —————
已知 已知 已知

扩展欧几里得求的是
ax+by=d
a已知,b已知,d是a和b的最大公约数,求x,y
因此把上式的a替换乘(m-n),b替换成L。
式子变成(m-n)x+(-y)L=d
LL d = exgcd(m - n, L, x, y);
如果(b-a)%d不等于0,两只青蛙永远不会碰面,不是最大公约数
如果(b-a)%d等于零,把(m-n)x+(-y)L=d扩大(b-a)/d倍后,x就是结果。
//x0放大是因为 x0是(m-n)x-yl=gcd(m-n,l) 的方程的解 而答案要求的是
//(m-n)x-y
l=b-a的b-a,此x0非彼x0,所以只有x0的问题是需要放大的

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

LL exgcd(LL a, LL b, LL &x, LL &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }

    LL d = exgcd(b, a % b, y, x);
    y -= a / b * x;

    return d;
}

int main()
{
    LL a, b, m, n, L;
    cin >> a >> b >> m >> n >> L;

    LL x, y;
    LL d = exgcd(m - n, L, x, y);
    if ((b - a) % d) puts("Impossible");
    else
    {
        x *= (b - a) / d;
        LL t = abs(L / d);
        cout << (x % t + t) % t << endl;
    }

    return 0;
}

最幸运的数 求多少个8连接在一起可以变成c的倍数 https://www.acwing.com/problem/content/204/

变成求 9L |8×(10^x−1) 的最小正整数 x
最终变成求解满足 10^x≡1(modC) 的最小正整数 x

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

typedef long long LL;

LL qmul(LL a, LL k, LL p) {
    LL res = 0;
    while (k) {
        if (k & 1) res = (res + a) % p;
        k >>= 1;    
        a = (a + a) % p;
    }
    return res;
}

LL get_euler(LL C) {
    LL res = C;
    for (LL i = 2; i <= C / i; i ++ ) 
        if (C % i == 0) {
            while (C % i == 0) C /= i;
            res = res / i * (i - 1);
        }
    if (C > 1) res = res / C * (C - 1);
    return res;
}

LL qmi(LL a, LL k, LL p) {
    LL res = 1;
    while (k) {
        if (k & 1) res = qmul(res, a, p);
        k >>= 1;
        a = qmul(a, a, p);
    }
    return res;
}

LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
}

int main() {
    int T = 1;
    LL L;
    while (cin >> L, L) {
        int d = 1;
        while (L % (d * 2) == 0 && d * 2 <= 8) d *= 2;
        // 求C 和 phi(C)
        LL C = 9 * L / d;
        LL phi = get_euler(C);

        LL res = 1e18;

        // 用gcd有一定的常数,因为C较大 
        // if (gcd(10, C) != 1) res = 0;
        // 判断10和C是否互质,不互质输出0
        if (C % 2 == 0 || C % 5 == 0) res = 0;

        // 枚举phi(C)的所有约数
        for (LL d = 1; d * d <= phi; d ++ ) // 约数d可能爆int 根号枚举
            if (phi % d == 0) {//如果是约数
                if (qmi(10, d, C) == 1) res = min(res, d);//膜等于1的话
                if (qmi(10, phi / d, C) == 1) res = min(res, phi / d);
            }
        printf("Case %d: %lld\n", T ++ , res);
    }
    return 0;
}

posted @ 2022-08-08 21:10  liang302  阅读(163)  评论(0编辑  收藏  举报