[牛客多校第九场]Quadratic equation(二次剩余)

[牛客多校第九场]Quadratic equation(二次剩余)_第1张图片

题意:

给定两个数字在模1e9 + 7意义下x + y的和以及x和y的乘积,求x和y

题目分析

由于x和y的取值范围,我们可以得到x + y的范围为 0 <= x + y < 2 * p,那么对于第一个式子我们可以得到: x + y = b 或者 x + y = p + b的两种情况.
对于第一种情况,将第一个式子代入第二个式子可得
y * (b - y) = k * p + c
移项得,y ^ 2 - b * y + k * p + c = 0
如果y要有整数解,当且仅当 b ^ b - 4 * (k * p + c) 为完全平方数,从而得到如下方程
a ^ 2 = b * b - 4 * (k * p + c)
对两边同时模p可得
a ^ 2 ≡b * b - 4 * c (mod p)
从而转化为一个二次剩余的问题

二次剩余:

当时比赛的时候用下面的博客魔改了一下过了,博客里边有简单的证明
https://blog.csdn.net/acdreamers/article/details/10182281
在比赛之后又参考了下边的博客,才真正理解了这个神奇的东西
https://blog.csdn.net/a_crazy_czy/article/details/51959546

Part one 二次剩余的基本概念

在数论中,特别在同余理论里,一个整数 d \bm{d} d对另一个整数 p \bm{p} p 的二次剩余(英语:Quadratic residue)指X的平方 X 2 \bm{X^2} X2 除以 p \bm{p} p得到的余数。
当存在某个 X \bm{X} X X 2 ≡ d ( m o d p ) \bm{X^2≡d(mod p) } X2d(modp) 式子成立时,称 “ d \bm{d} d 是模 p \bm{p} p 的二次剩余 ”
当对任意 X \bm{X} X,上式都不成立时,称 “ d \bm{d} d 是模 p \bm{p} p 的二次非剩余 ”

关于二次剩余的判定,可以用欧拉准则来判断,具体方法如下:

p 是奇质数且 p 不能整除 d ,则:
d 是模 p 的二次剩余当且仅当: d p − 1 2 ≡ 1 ( m o d p ) \bm{d^\frac{p-1}{2}≡ 1(mod p)} d2p11(modp)
d 是模 p 的二次非剩余当且仅当: d p − 1 2 ≡ − 1 ( m o d p ) \bm{d^\frac{p-1}{2}≡ -1(mod p)} d2p11(modp)
以勒让德符号表示,即为: d p − 1 2 ≡ ( d p ) m o d p {\displaystyle d^{\frac {p-1}{2}}\equiv\left({\frac {d}{p}}\right){mod {p}}} d2p1(pd)modp
其中勒让德符号的定义如下:在这里插入图片描述

欧拉从充分性和必要性两个方面证明了上述结论,给出的证明如下:

首先,由于 p {\displaystyle p} p是一个奇素数,由费马小定理, d p − 1 ≡ 1 ( m o d p ) {\displaystyle d^{p-1}\equiv 1{\pmod {p}}} dp11(modp)。但是 p − 1 {\displaystyle} p-1 p1是一个偶数,
所以有 ( d p − 1 2 − 1 ) ⋅ ( d p − 1 2 + 1 ) ≡ 0 ( m o d p ) {\displaystyle (d^{\frac {p-1}{2}}-1)\cdot (d^{\frac {p-1}{2}}+1)\equiv 0{\pmod {p}}} (d2p11)(d2p1+1)0(modp)
p {\displaystyle}p p是一个素数,所以 d p − 1 2 − 1 {\displaystyle d^{\frac {p-1}{2}}-1} d2p11 d p − 1 2 + 1 {\displaystyle d^{\frac {p-1}{2}}+1} d2p1+1中必有一个是 p {\displaystyle }p p 的倍数。因此 d p − 1 2 {\displaystyle d^{\frac {p-1}{2}}} d2p1 p {\displaystyle p} p的余数必然是 1 1 1 − 1 -1 1

必要性:

证明若 d {\displaystyle} d d是模 p {\displaystyle} p p的二次剩余,则 d p − 1 2 ≡ 1 ( m o d p ) {\displaystyle d^{\frac {p-1}{2}}\equiv 1{\pmod {p}}} d2p11(modp)
d {\displaystyle } d d是模 p {\displaystyle } p p的二次剩余,则存在 x 2 ≡ d ( m o d p ) {\displaystyle x^{2}\equiv d{\pmod {p}}} x2d(modp) p {\displaystyle } p p d , x {\displaystyle d,x} d,x互质。根据费马小定理得:
d p − 1 2 ≡ x p − 1 ≡ 1 ( m o d p ) {\displaystyle d^{\frac {p-1}{2}}\equiv x^{p-1}\equiv 1{\pmod {p}}} d2p1xp11(modp)

充分性:

证明若 d p − 1 2 ≡ 1 ( m o d p ) {\displaystyle d^{\frac {p-1}{2}}\equiv 1{\pmod {p}}} d2p11(modp),则 d {\displaystyle } d d是模 p {\displaystyle } p p的二次剩余 p {\displaystyle } p p是一个奇素数,所以关于 p {\displaystyle } p p的原根存在。设 a {\displaystyle } a a p {\displaystyle } p p的一个原根,
则存在 1 ≤ j ≤ p − 1 {\displaystyle 1\leq j\leq p-1} 1jp1,使得 d = a j d = a j {\displaystyle d=a^{j}} {\displaystyle d=a^{j}} d=ajd=aj
于是 a j p − 1 2 ≡ 1 ( m o d p ) {\displaystyle a^{j{\frac {p-1}{2}}}\equiv 1{\pmod {p}}} aj2p11(modp)
a {\displaystyle } a a p {\displaystyle }p p的一个原根,因此 a {\displaystyle } a a p {\displaystyle } p p的指数是 p − 1 {\displaystyle} p-1 p1,于是 p − 1 {\displaystyle} p-1 p1整除 j ( p − 1 ) 2 {\displaystyle {\frac {j(p-1)}{2}}} 2j(p1)。这说明 j {\displaystyle } j j是一个偶数。令 i = j 2 {\displaystyle i={\frac {j}{2}}} i=2j,就有 ( a i ) 2 = a 2 i = d {\displaystyle (a^{i})^{2}=a^{2i}=d} (ai)2=a2i=d d {\displaystyle } d d是模 p {\displaystyle } p p的二次剩余。

Part two 二次剩余的问题求解(随机大法好!)

问题描述:
对于给定的 d d d p p p 判断 d d d 是否是 p p p 的二次剩余,
如果是,则输出 X 2 ≡ d ( m o d p ) X^2\equiv d{\pmod {p}} X2d(modp)的一个解,
其中, p p p 是奇素数。
题目传送门:http://acm.timus.ru/problem.aspx?space=1&num=1132

引理:

对于 0 < = X < = p − 1 , X p − 1 2 ≡ 1 ( m o d p ) 0 <= X < = p - 1,X^{\frac{p - 1}{2}}\equiv 1{\pmod {p}} 0<=X<=p1,X2p11(modp) p − 1 2 {\frac{p - 1}{2}} 2p1个解
证明如下:
u , v u,v u,v X X X的两个解,我们可以得到 u 2 − v 2 ≡ 0 ( m o d p ) u^2 - v ^ 2\equiv 0{\pmod{p}} u2v20(modp)
进一步化简得到 ( u − v ) ∗ ( u + v ) ≡ 0 ( m o d p ) (u - v)*(u + v)\equiv0{\pmod{p}} (uv)(u+v)0(modp),由 X X X的范围我们可以指导,
p ∣ ( u + v ) p | (u + v) p(u+v),并且 u + v = p u + v = p u+v=p,所以有 p − 1 2 {\frac{p - 1}{2}} 2p1个解。

Cipolla算法

为了求出 X X X的解,我们通过随机数找到一个满足 ( a − n 2 p ) (\frac{a - n ^ 2}{p}) (pan2)为-1的根据引理我们可以知道这样的 a a a一共有 p − 1 2 \frac{p - 1}{2} 2p1个,因此求出这样的 a a a的期望次数为 p − 1 2 p \frac{p - 1}{2 p} 2pp1约为 1 2 \frac{1}{2} 21,基本上我们随机两次就可以得到这样的 a a a,一般我们会随机比较多的次数防止自己脸黑。
在的得到这样的一个 a a a之后我们做如下的处理:

①取 a 2 − n \sqrt{a ^ 2 - n} a2n 为基本的虚数单位,设为 w w w,类比 − 1 \sqrt{-1} 1 作为 i i i
②构造一个与当前虚数单位所对应的数域,类比于实数到复数,则在这个数域中所有的数字都可以表示为 a + b w a + bw a+bw的形式
③验证当前数域的运算的封闭性、交换律、结合律、分配律,即验证它是一个合法的数域

[牛客多校第九场]Quadratic equation(二次剩余)_第2张图片
对于这个数域,我们可以得到如下的结论:
w p ≡ − w ( m o d p ) w^p\equiv-w{\pmod{p}} wpw(modp)
证明:根据 ( w 2 p ) (\frac{w ^ 2}{p}) (pw2) − 1 -1 1我们可以知道, w 2 p − 1 2 ≡ − 1 ( m o d p ) {w^2}^{\frac{p-1}{2}}\equiv -1\pmod{p} w22p11(modp),从而我们知道 w p = w p − 1 ∗ w , w p ≡ − w ( m o d p ) w^p = w ^{p - 1} * w,w^p\equiv-w\pmod p wp=wp1w,wpw(modp)
( a + b ) p ≡ a p + b p ( m o d p ) (a + b) ^ p \equiv a ^ p + b ^ p{\pmod p} (a+b)pap+bp(modp)
证明见我之前写的题解:https://blog.csdn.net/z472421519/article/details/99842319

我们取 X ≡ ( a + w ) p + 1 2 ( m o d p ) X \equiv (a + w) ^{\frac{p + 1}{2}}\pmod p X(a+w)2p+1(modp)
我们可以得到 X 2 ≡ ( a + w ) p + 1 ( m o d p ) X ^ 2 \equiv(a + w)^{p + 1} \pmod p X2(a+w)p+1(modp) X 2 ≡ ( a + w ) p ∗ ( a + w ) ( m o d p ) X ^ 2 \equiv(a + w)^{p} * (a + w) \pmod p X2(a+w)p(a+w)(modp)
利用刚才的结论 X 2 ≡ ( a p + w p ) ∗ ( a + w ) ( m o d p ) X ^ 2 \equiv(a^p + w^p) * (a + w) \pmod p X2(ap+wp)(a+w)(modp) X 2 ≡ ( a p − w ) ∗ ( a + w ) ( m o d p ) X ^ 2 \equiv(a^p-w) * (a + w) \pmod p X2(apw)(a+w)(modp)
再利用费马小定理 a p ≡ a ( m o d p ) a ^ p \equiv a \pmod p apa(modp) 得到,
X 2 ≡ ( a − w ) ∗ ( a + w ) ( m o d p ) X ^ 2 \equiv(a - w) * (a + w) \pmod p X2(aw)(a+w)(modp)
X 2 ≡ ( a 2 − w 2 ) ( m o d p ) X ^ 2 \equiv(a^2 - w^2) \pmod p X2(a2w2)(modp)
代入 w = a − n w = \sqrt{a - n} w=an
X 2 ≡ n ( m o d p ) X ^ 2 \equiv n \pmod p X2n(modp),即 X X X满足之前的二次剩余方程

代码

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
typedef long long LL;

LL quick_mod(LL a, LL b, LL m)
{
    LL ans = 1;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % m;
            b--;
        }
        b >>= 1;
        a = a * a % m;
    }
    return ans;
}

struct T
{
    LL p, d;
};

LL w;

//二次域乘法
T multi_er(T a, T b, LL m)
{
    T ans;
    ans.p = (a.p * b.p % m + a.d * b.d % m * w % m) % m;
    ans.d = (a.p * b.d % m + a.d * b.p % m) % m;
    return ans;
}

//二次域上快速幂
T power(T a, LL b, LL m)
{
    T ans;
    ans.p = 1;
    ans.d = 0;
    while(b)
    {
        if(b & 1)
        {
            ans = multi_er(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi_er(a, a, m);
    }
    return ans;
}

//求勒让德符号
LL Legendre(LL a, LL p)
{
    return quick_mod(a, (p-1)>>1, p);
}

LL mod(LL a, LL m)
{
    a %= m;
    if(a < 0) a += m;
    return a;
}

LL Solve(LL n,LL p)
{
    if(p == 2) return 1;
    if (Legendre(n, p) + 1 == p)
        return -1;
    LL a = -1, t;
    while(true)
    {
        a = rand() % p;
        t = a * a - n;
        w = mod(t, p);
        if(Legendre(w, p) + 1 == p) break;
    }
    T tmp;
    tmp.p = a;
    tmp.d = 1;
    T ans = power(tmp, (p + 1)>>1, p);
    return ans.p;
}

int main()
{
    LL t;
    scanf("%d", &t);
    while(t--)
    {
        LL n,p,N;
        LL x,y;
        scanf("%lld%lld",&x,&y);
        p = 1e9 + 7;
        n = x * x - 4 * y;
        N = (x + p) * (x + p) - 4 * y;
//        //printf("%lld",n);
        if(n == 0)
        {
            printf("%lld %lld\n",x / 2,x / 2);
            continue;
        }
        LL a;
        LL X,Y;
        bool suc = false;
        for(int i = 1;i <= 10;i++)
        {
            if(n > 0)
            {
                a = Solve(n, p);
                X = (x - a) / 2,Y = (x + a) / 2;
                if(((X + Y) % p == (x % p) && (X * Y) % p == y) && (X >= 0 && X <= p) && (Y >= 0 && Y <= p))
                {
                    suc = true;
                    break;
                }
            }
            if(N > 0)
            {
                a = Solve(N, p);
                X = (x + p - a) / 2,Y = (x + p + a) / 2;
                if(((X + Y) % p == (x % p) && (X * Y) % p == y) && (X >= 0 && X <= p) && (Y >= 0 && Y <= p))
                {
                    suc = true;
                    break;
                }
            }
        }
        if(suc)
            printf("%lld %lld\n",X,Y);
        else
            printf("-1 -1\n");
     }
    return 0;
}

不知道为啥有的时候会出错,考虑到随机算法的脸黑性,我加了个暴力判断,在运算超过十次之后就直接 − 1 , − 1 -1,-1 1,1输出

你可能感兴趣的:(数论)