• 二次剩余


    定理1:n(p-1)/2≡±1(mod p),p是奇素数。

    定理2:给出方程 x2≡n(mod p),其中p是奇素数,则方程有解当且仅当n(p-1)/2≡1(mod p)。

    定理3:若方程 x2≡w(mod p),其中p是奇素数无解,设a满足a2=w+n,则(a+sqrt(w))p+1≡n(mod p),也即对任意a2>w,则有(a+sqrt(w))p+1≡a2-w(mod p)。

    下面开始正文。我们为啥要搞这个二次剩余呢?问题的起源在于,如果我们已知一个 x2≡n(mod p),我们想知道x对p的模,也即,同余方程两边同时开根号,这能做到吗?

    当n不是p的二次剩余时,显然这样的x并不存在,自然无法开根号。但是当n是p的二次剩余时,一定能,而且若n不等于0,则一定有两个x,满足x1+x2≡0(mod p),均是该二次剩余方程的解。

    给出求sqrt(n)的板子,如果不存在返回-1。

     1 #include <iostream>   
     2 #include <ctime>
     3 using namespace std;
     4 typedef long long ll;
     5 #define random(a,b) (rand()%(b-a+1)+a)
     6 ll quick_mod(ll a, ll b, ll c){
     7     ll ans = 1;
     8     while(b){
     9         if(b%2==1) ans=(ans*a)%c;
    10         b/=2;
    11         a=(a*a)%c;
    12     }
    13     return ans;
    14 }
    15 ll p;
    16 ll w;//二次域的D值,使同余方程无解的那个值 
    17 struct QuadraticField//二次域
    18 {
    19     ll x, y;
    20     QuadraticField operator*(QuadraticField T)//二次域乘法重载
    21     {
    22         QuadraticField ans;
    23         ans.x = (this->x*T.x%p + this->y*T.y%p*w%p) % p;
    24         ans.y = (this->x*T.y%p + this->y*T.x%p) % p;
    25         return ans;
    26     }
    27     QuadraticField operator^(ll b)//二次域快速幂
    28     {
    29         QuadraticField ans;
    30         QuadraticField a = *this;
    31         ans.x = 1;
    32         ans.y = 0;
    33         while (b)
    34         {
    35             if (b & 1)
    36             {
    37                 ans = ans*a;
    38                 b--;
    39             }
    40             b /= 2;
    41             a = a*a;
    42         }
    43         return ans;
    44     }
    45 };
    46  
    47 ll Legender(ll a)//求勒让德符号
    48 {
    49     ll ans=quick_mod(a, (p - 1) / 2, p);
    50     if (ans + 1 == p)//如果ans的值为-1,%p之后会变成p-1。
    51         return -1;
    52     else
    53         return ans;
    54 }
    55  
    56 ll Getw(ll n, ll a)//根据随机出来a的值确定对应w的值
    57 {
    58     return ((a*a - n) % p + p) % p;//防爆处理
    59 }
    60  
    61 ll Solve(ll n)//没有解返回-1 
    62 {
    63     ll a;
    64     if (p == 2)//当p为2的时候,n只会是0或1,然后0和1就是对应的解
    65         return n;
    66     if (Legender(n) == -1)//无解
    67         return -1;
    68     srand((unsigned)time(NULL));
    69     while (1)//随机a的值直到有解
    70     {
    71         a = random(0, p - 1);
    72         w = Getw(n, a);
    73         if (Legender(w) == -1)
    74             break;
    75     }
    76     QuadraticField ans,res;
    77     res.x = a;
    78     res.y = 1;//res的值就是a+根号w
    79     ans = res ^ ((p + 1) / 2);
    80     return ans.x;
    81 }
    82  
    83 int main()
    84 {
    85     ll n,ans1,ans2;
    86     while (scanf("%lld%lld",&n,&p)!=EOF)
    87     {
    88         n %= p;
    89         ans1 = Solve(n);
    90         ans2 = p - ans1;//一组解的和是p
    91     }
    92 }
  • 相关阅读:
    TMainMenu 类 手动建立菜单 : 指定快捷键《转》
    确定多重选择列表控件 (List Control) 中的选定内容
    【320K】大峡谷The Music of The Grand Canyon
    35种音乐的分类
    ASP中常用的变量命名规则
    关于DBF文件导入问题
    ASP.NET里的变量命名规则
    ASP中数据库安全问题之我见
    用err.raise自定义错误信息
    关于编程风格的讨论 PioneerMan(原作)
  • 原文地址:https://www.cnblogs.com/St-Lovaer/p/11767755.html
Copyright © 2020-2023  润新知