동일 방정식과 확장 유클리드 알고리즘

x와 y의 최대공약수가 d일 때 (x,y)=d 방정식으로 변환하면 ax+by=d 매개변수 x와 y에 대한 표현식 x y의 부호는 상관없음 x=x0+kb/d (반대쪽을 더함) y=y0-ka/d

//확장 유클리드 알고리즘
int extended_gcd(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 = extended_gcd(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 extended_gcd(int a, int b, int &x, int &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }

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

    return d;
}

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

    int x, y;
    extended_gcd(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 = extended_gcd(m - n, L, x, y); (b-a)%d가 0이 아니면 두 개구리는 만날 수 없음 (최대공약수가 아님) (b-a)%d가 0이면 (m-n)x+(-y)L=d를 (b-a)/d배 확장하면 x가 해가 됨 //x0가 확장되는 이유는 x0가 (m-n)x-yl=gcd(m-n,l) 방정식의 해이고 //답은 (m-n)x-yl=b-a를 만족하는 x0이기 때문에 다른 x0이므로 확장이 필요

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

using namespace std;

typedef long long LL;

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

    LL d = extended_gcd(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 = extended_gcd(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 fast_multiply(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 euler_phi(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 fast_pow(LL a, LL k, LL p) {
    LL res = 1;
    while (k) {
        if (k & 1) res = fast_multiply(res, a, p);
        k >>= 1;
        a = fast_multiply(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 = euler_phi(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 (fast_pow(10, d, C) == 1) res = min(res, d);//나머지가 1이면
                if (fast_pow(10, phi / d, C) == 1) res = min(res, phi / d);
            }
        printf("Case %d: %lld\n", T ++ , res);
    }
    return 0;
}


태그: 확장 유클리드 동일 방정식 수론 알고리즘 모듈러 연산

6월 6일 21:47에 게시됨