zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第九场)B Quadratic equation (平方剩余)

    ((x+y)equiv bpmod p)

    ((x imes y)equiv cpmod p)

    由第一个式子可知:(x+y=b~or~x+y=b+p)

    先任选一个代入到第二个式子里得

    [(x imes(b-x))equiv cpmod p Rightarrow (2*x-b)^2equiv (b^2-4c)pmod p ]

    解二次剩余方程 (q^2equiv apmod p)

    因为这个方程去查了很多资料

    1. 欧拉准则

    对于(x^2equiv apmod p)

    [a^{p-1over 2} = egin{cases} 1pmod p & {如果存在一个x使得a equiv x^2 pmod p}\ -1pmod p & {如果不存在x使得上式成立} end{cases} ]

    证明:

    先不考虑a为0的情况。

    已知 ((p-x)^2equiv x^2pmod p), 这是因为(p^2-2xp+x^2equiv x^2 pmod p)

    所有有(p-1over 2) 个不同的二次剩余,即(1^2,2^2,cdots,({p-1over 2}) pmod p) (因为前一半和后一半相同了)

    (a^{p-1}equiv 1 pmod p), 可以写为(({a^{p-1over 2}-1})({a^{p-1over 2}} + 1)equiv 0pmod p)

    上式中的前后两个因子,必须有一个为0,由(Lagrangs's theorem) 可知 k次多项式最多 k 个解,所以(a^{p-1over 2}-1equiv 0pmod p) 有最多 (p-1over 2)个解。

    (x^2equiv a), 所以(a^{p-1over 2} equiv (x^2)^{p-1over 2} equiv 1pmod p)

    所以每一个平方剩余都可以使得第一个因子为0,非0平方剩余最少有(p-1over 2)个,所以这与上面方程的解正好对应起来,也就是说使得(a^{p-1over 2}equiv 1)成立的(a) 都是(p) 的二次剩余。同理可知使得(a^{p-1over 2} equiv -1)成立的(a)都是(p)的非二次剩余。

    2. 求解二次剩余

    本题比较特殊,(pequiv 3pmod 4) ,那么根据上面推出来的

    [a^{p-1over 2}equiv1~Rightarrow~ a^{p+1over 2}equiv x^2~Rightarrow a^{p+1over 4}equiv x ]

    对于更一般的(p) , 可以参考: http://xbgjxt.swu.edu.cn/jsuns/html/jsuns/2019/1/201901009.htm

    综述:

    1. 根据欧拉准则来判断是否有解
    2. 有解则求出原题中的x 与 y输出
    3. 无解则输出-1

    标程代码:

    int t, p = 1000000007;
    //快速幂代码
    long long pow(long long x, long long y, long long p) {
    }
    int main() {
        cin >> t;
        for (int tt = 0; tt < t; tt++) {
            long long b, c;
            cin >> b >> c;
            long long d = (b * b - 4 * c) % p;
            if (d < 0) {
                d += p;
            }
            if (d != 0 && pow(d, (p - 1) / 2, p) != 1) {//如果无解,需要注意d为0的情况
                cout << -1 << ' ' << -1 << endl;
            } else {
                long long r = pow(d, (p + 1) / 4, p);
                long long x = (b + r) * pow(2, p - 2, p) % p;
                long long y = (b - r) * pow(2, p - 2, p) % p;
                if (x < 0)x += p;
                if (y < 0)y += p;
                if (x > y) swap(x, y);
                cout << x << ' ' << y << endl;
            }
        }
    }
    

    自己的代码

    const ll mod = 1e9+7;
    ll pow_mod(ll a,ll i,ll n){
        if(i == 0)return 1 % n;
        ll tmp = pow_mod(a, i>> 1,n);
        tmp = tmp * tmp % n;
        if(i & 1)tmp = tmp * a % n;
        return tmp;
    }
    //红宝书模板代码,求解模p下二次剩余为a的解
    ll modsqr(ll a,ll n){
        if(a == 0)return 0;
        ll b,k,i,x;
        if(n == 2)return a % n;
        if(pow_mod(a,(n-1)/2,n) == 1){
            if(n % 4 == 3)//本题中只会进入下面这个case
                x = pow_mod(a,(n+1)/4,n);
            else{
                for(b = 1;pow_mod(b,(n-1)/2,n) == 1;b++);
                i = (n-1)/2;
                k = 0;
                do{
                    i/=2;
                    k/=2;
                    if((pow_mod(a,i,n) * pow_mod(b,k,n) + 1) % n == 0)
                        k += (n-1) / 2;
                }while(i % 2 == 0);
                x = (pow_mod(a,(i+1)/2,n) * pow_mod(b,k/2,n))%n;
            }
            if(x * 2 > n)x = n-x;
            return x;
        }
        return -1;
    }
    int main() 
    {
        int T;cin>>T;
        while(T--){
            ll b,c;
            scanf("%lld%lld",&b,&c);
            ll q,a;
            a = ((b*b - c * 4)%mod + mod) % mod;
            q = modsqr(a,mod);
            if(q == -1){//无解情况
                puts("-1 -1");
                continue;
            }
            //很蠢的分了两种情况....其实乘一个2的逆元即可
            ll x = (q + b) / 2;
            ll y = mod + b - x;
            x = (x % mod + mod) % mod;
            y = (y % mod + mod) % mod;
            if((x * y) % mod == c){
                if(x > y)swap(x,y);
                printf("%lld %lld
    ",x,y);continue;
            }
            x = (q + b + mod)/2;
            y = b - x;
            x = (x % mod + mod) % mod;
            y = (y % mod + mod) % mod;
            if((x * y) % mod == c){
                if(x > y)swap(x,y);
                printf("%lld %lld
    ",x,y);continue;
            }
            puts("-1 -1");
        }
        return 0;
    }
    

    参考资料:

    https://en.wikipedia.org/wiki/Quadratic_residue

    https://en.wikipedia.org/wiki/Euler's_criterion

  • 相关阅读:
    NetCore+Dapper WebApi架构搭建(三):添加实体和仓储
    NetCore+Dapper WebApi架构搭建(二):底层封装
    NetCore+Dapper WebApi架构搭建(一):基本框架
    net core WebApi——缓存神器Redis
    net core Webapi基础工程搭建(六)——数据库操作_Part 2
    net core Webapi基础工程搭建(七)——小试AOP及常规测试_Part 2
    springBoot+mybatisPlus小demo
    JAVA并发(一)
    tomcat解析
    JAVA并发-线程状态
  • 原文地址:https://www.cnblogs.com/1625--H/p/11382466.html
Copyright © 2011-2022 走看看