二次剩余

素数模的二次同余方程

 

求解 

x * x = a(mod p)  p为奇素数,输出 x 的可行解
// 输入 a 和 mod ,满足式子 x * x = a(mod p)  p为奇素数,输出 x 的可行解
#include<cstdio>

using namespace std;
#define LL long long
LL Pow(LL a,LL b,LL p) {
    LL res = 1;
    for (; b; a = 1LL * a * a % p, b >>= 1)
        if (b & 1) res = 1LL * a * res % p;
    return res;
}

bool Legendre(LL a,LL p) {
    return Pow(a, p - 1 >> 1, p) == 1;
}

void modsqr(LL a,LL p) {
    LL x;
    LL i, k, b;
    if (p == 2) x = a % p;
    else if (p % 4 == 3) x = Pow(a, p + 1 >> 2, p);
    else {
        for (b = 1; Legendre(b, p); ++b);
        i = p - 1 >> 1;
        k = 0;
        do {
            i >>= 1;
            k >>= 1;
            if (!((1LL * Pow(a, i, p) * Pow(b, k, p) + 1) % p)) k += p - 1 >> 1;
        } while (!(i & 1));
        x = 1LL * Pow(a, i + 1 >> 1, p) * Pow(b, k >> 1, p) % p;
    }
    if (p - x < x) x = p - x;
    if (x == p - x) printf("%lld\n", x);        //  输出解
    else printf("%lld %lld\n", x, p - x);
}

int main() {

    int T;
    scanf("%d", &T);
    LL a, p;
    while (T--) {
        scanf("%lld %lld", &a, &p);
        a %= p;
        if (!Legendre(a, p)) {
            puts("No root");
            continue;
        }
        modsqr(a, p);
    }
    return 0;
}

 

牛客第九场Quadratic equation

#include<cstdio>

using namespace std;
const long long mod = 1e9 + 7;
#define LL long long
LL B,C;
LL Pow(LL a,LL b,LL p) {
    LL res = 1;
    for (; b; a = 1LL * a * a % p, b >>= 1)
        if (b & 1) res = 1LL * a * res % p;
    return res;
}

bool Legendre(LL a,LL p) {
    return Pow(a, p - 1 >> 1, p) == 1;
}
bool check(LL b,LL x) {
    if ((b + x) % 2 == 1)
        return false;
    LL xx = (x + b) / 2;
    LL yy = (b - x) / 2;
    if (0 <= xx && xx < mod && 0 <= yy && yy < mod)
        return true;
    return false;
}
void modsqr(LL a,LL p) {
    LL x;
    LL i, k, b;
    if (p == 2) x = a % p;
    else if (p % 4 == 3) x = Pow(a, p + 1 >> 2, p);
    else {
        for (b = 1; Legendre(b, p); ++b);
        i = p - 1 >> 1;
        k = 0;
        do {
            i >>= 1;
            k >>= 1;
            if (!((1LL * Pow(a, i, p) * Pow(b, k, p) + 1) % p)) k += p - 1 >> 1;
        } while (!(i & 1));
        x = 1LL * Pow(a, i + 1 >> 1, p) * Pow(b, k >> 1, p) % p;
    }
    if (p - x < x) x = p - x;
    if (x == p - x) {
        if (check(B, x))
            printf("%lld %lld\n", (B - x) / 2, (B + x) / 2);
        else if (check(B + p, x))
            printf("%lld %lld\n", (B + p - x) / 2, 1LL * (B + p + x) / 2);
        else puts("-1 -1");
    } else {
        if (check(B, x)) printf("%lld %lld\n", (B - x) / 2, (B + x) / 2);
        else if (check(B, p - x)) printf("%lld %lld\n", (B - p + x) / 2, (B - x + p) / 2);
        else if (check(B + p, x)) printf("%lld %lld\n", (B - x + p) / 2, (B + x + p) / 2);
        else if (check(B + p, p - x)) printf("%lld %lld\n", (B + x) / 2, (B - x + 2 * p) / 2);
        else puts("-1 -1");
    }
}

int main() {

    int T;
    scanf("%d", &T);
    LL a;
    while (T--) {
        scanf("%lld %lld", &B, &C);
        a = (B * B % mod - 4LL * C % mod + mod);
        a %= mod;
        if (a == 0) {
            if (B % 2 == 0) printf("%lld %lld\n", B / 2, B / 2);
            else printf("%lld %lld\n", (B + mod) / 2, (B + mod) / 2);
            continue;
        }
        if (!Legendre(a, mod)) {
            puts("-1 -1");
            continue;
        }
        modsqr(a, mod);
    }
    return 0;
}
View Code

 

posted @ 2019-08-16 13:33  千摆渡Qbd  阅读(189)  评论(0编辑  收藏  举报