• 数学:二次剩余与n次剩余


    二次剩余求的是这个东西

    如果给定x,再给定若干个大的质数p,如果结果a相同,那么x是完全平方数?

     1 /*poj 1808
     2   题意:
     3   判断平方剩余,即判断(x^2)%p=a是否有解。
     4   限制:
     5   |a| <= 1e9 && a % p !=0; 2 < p < 1e9 && p为奇素数。
     6   思路:
     7   用欧拉准则计算勒让德符号(用来判断平方剩余)
     8  */
     9 #include<iostream>
    10 #include<cstdio>
    11 using namespace std;
    12 #define LL __int64
    13 LL a_b_MOD_c(LL a,LL b,LL mod){
    14     LL ret = 1;
    15     a %= mod;
    16     while(b){
    17         if(b & 1) ret = ret * a % mod;
    18         a = a * a % mod;
    19         b >>= 1;
    20     }
    21     return ret;
    22 }
    23 //(x^2)%n=a 求平方剩余,n必须是奇素数
    24 //注意:如果a为负,则看题意,是否要化为a=(a%n+n)%n
    25 int modsqr(int a,int n){
    26     int b,k,i,x;
    27     if(n==2) return a%n;
    28     if(a_b_MOD_c(a,(n-1)/2,n)==1){
    29         if(n%4==3)
    30             x=a_b_MOD_c(a,(n+1)/4,n);
    31         else{
    32             for(b=1;a_b_MOD_c(b,(n-1)/2,n)==1;b++){
    33                 i=(n-1)/2;
    34                 k=0;
    35             }
    36             do{
    37                 i/=2;
    38                 k/=2;
    39                 if((a_b_MOD_c(a,i,n)*a_b_MOD_c(b,k,n)+1)%n==0)
    40                     k+=(n-1)/2;
    41             }
    42             while(i%2==0);
    43             x=(a_b_MOD_c(a,(i+1)/2,n)*a_b_MOD_c(b,k/2,n))%n;
    44         }
    45         if(x*2>n)
    46             x=n-x;
    47         return x;
    48     }
    49     return -1;
    50 }
    51 //用欧拉准则计算勒让德符号(用来判断平方剩余)
    52 //表示为(a|p) a为整数,p为奇素数(所以m=2不适用勒让德符号),有三种情况。
    53 //1. (a|p)=0, if(a%p==0)
    54 //2. (a|p)=1, if(a%p!=0 && (x^2)%p=a 有整数解)
    55 //3. (a|p)=-1,if((x^2)%p=a 无整数解)
    56 //注意:如果a为负,则看题意,是否要化为a=(a%p+p)%p
    57 int lrd(LL a,LL p){
    58     LL ret=a_b_MOD_c(a,(p-1)>>1,p);
    59     if(ret==1)
    60         return 1;
    61     return -1;
    62 }
    63 int main(){
    64     int T,cas=0;
    65     int a,n;
    66     scanf("%d",&T);
    67     while(T--){
    68         scanf("%d%d",&a,&n);
    69         a=(a+n)%n;    //以后注意给出余数的时候,要注意它是不是负的
    70         
    71         //求平方剩余
    72         //cout<<modsqr(a,n)<<endl;
    73         printf("Scenario #%d:
    %d
    
    ",++cas,lrd(a,n));
    74     }
    75     return 0;
    76 }

    然后是n次剩余

      1 /*hdu 3930
      2   题意:
      3   给定newx, k, m, 方程 (x^k)%m=newx, 求在模m意义下的所有解x。
      4   限制:
      5   0 <= newx, m, k <= 1.5*10^15; m是素数。
      6   思路:
      7   N次剩余
      8  */
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <cmath>
     12 #include <cstring>
     13 #include <vector>
     14 #include <algorithm>
     15 using namespace std;
     16 #define LL __int64
     17 #define PB push_back
     18 LL mul(LL a,LL b,LL m){
     19     LL ret = 0;
     20     a %= m;
     21     while(b){
     22         if(b & 1) ret = (ret + a) % m;
     23         a = (a + a) % m;
     24         b >>= 1;
     25     }
     26     return ret;
     27 }
     28 LL a_b_MOD_c(LL a,LL b,LL m){
     29     LL ret = 1;
     30     a %= m;
     31     while(b){
     32         if(b&1) ret = mul(ret,a,m);
     33         a = mul(a,a,m);
     34         b >>= 1;
     35     }
     36     return ret;
     37 }
     38  
     39 LL ext_gcd(LL a,LL b,LL &x,LL &y){
     40     if(b==0) { x=1, y=0; return a; }
     41     LL ret= ext_gcd(b,a%b,y,x);
     42     y-= a/b*x;
     43     return ret;
     44 }
     45 vector<LL> a;
     46 bool g_test(LL g,LL p){
     47     for(LL i=0;i<a.size();++i)
     48         if(a_b_MOD_c(g,(p-1)/a[i],p)==1)
     49             return 0;
     50     return 1;
     51 }
     52 LL pri_root(LL p){
     53     a.clear();
     54     LL tmp=p-1;
     55     for(LL i=2;i<=tmp/i;++i)
     56         if(tmp%i==0){
     57             a.push_back(i);
     58             while(tmp%i==0)
     59                 tmp/=i;
     60         }
     61     if(tmp!=1)
     62         a.push_back(tmp);
     63     LL g=1;
     64     while(true){
     65         if(g_test(g,p))
     66             return g;
     67         ++g;
     68     }
     69 }
     70 const int HASH_MOD=9876543;
     71 LL key[HASH_MOD], val[HASH_MOD];
     72 int head[HASH_MOD], next[HASH_MOD];
     73 struct Hash{
     74     int tot;
     75     void init(){
     76         memset(head, -1, sizeof(head));
     77         tot = 0;
     78     }
     79     LL insert(LL x, LL y){
     80         int k = x % HASH_MOD;
     81         key[tot] = x;
     82         val[tot] = y;
     83         next[tot] = head[k];
     84         head[k] = tot++;
     85     }
     86     LL find(LL x){
     87         int k = x % HASH_MOD;
     88         for(int i = head[k]; i != -1; i = next[i])
     89             if(key[i] == x)
     90                 return val[i];
     91         return -1;
     92     }
     93 }hs;
     94 //求解模方程a^x=b(mod m),n为素数,无解返回-1  
     95 //注意:要求0 < a < m; 0 <= b < m; 否则按题意自己转化。
     96 //复杂度O(sqrt(m))
     97 LL log_mod(LL a, LL b, LL m){
     98     hs.init();
     99     LL s = ceil(sqrt(m + 0.5));
    100     LL cur = 1;
    101     for (int i = 0; i < s; ++i){
    102         if(hs.find(cur)==-1) hs.insert(cur,i);    //记得先判重,在插入
    103         cur = cur * a % m;
    104     }
    105  
    106     LL v = a_b_MOD_c(a, (m - s - 1 + m) % m, m);
    107     for(int i = 0; i < s; ++i){
    108         LL tmp = hs.find(b);
    109         if(tmp!=-1)
    110             return s * i + tmp;
    111         b=b*v%m;
    112     }
    113     return -1;
    114 }
    115 /*n次剩余
    116   任务:
    117   给定N, a, p, 求出(x^N)%p=a 在模p意义下的所有解x。
    118   说明:
    119   令g为p的原根,因为p为素数,所以phi(p)=p-1。
    120   由原根的性质得:
    121   如果g为p的原根,则:g^i mod p != g^j mod p (p为素数), 其中i != j且i, j介於1至(p-1)之间
    122   所以,可以设g^y=x, g^t=a,则有:
    123   g^(y*N)%p=g^t
    124   又由原根的性质:
    125   g^(y*N)%p=g^t -> (y*N)%(p-1)=t (此方程可以由拓展欧几里得解)
    126   另外g^t=a可以由离散对数求出
    127  */
    128 vector<LL> residue(LL p, LL N, LL a){
    129     LL g = pri_root(p);
    130     g %= p;
    131     LL m = log_mod(g, a, p);
    132     vector<LL> ret;
    133     if(a == 0){
    134         ret.PB(0);
    135         return ret;
    136     }
    137     if(m == -1)
    138         return ret;
    139     LL A = N, B = p - 1, C = m, x, y;
    140     LL d = ext_gcd(A, B, x, y);
    141     if(C % d != 0) return ret;
    142     x = x * (C / d) % B;
    143     LL delta = B / d;
    144     for(int i = 0; i < d; ++i){
    145         x = ((x + delta) % B + B) % B;
    146         ret.PB(a_b_MOD_c(g, x, p));
    147     }
    148     sort(ret.begin(), ret.end());
    149     ret.erase(unique(ret.begin(), ret.end()), ret.end());
    150     return ret;
    151 }
    152 int main(){
    153     int cas = 0;
    154     LL k,m,newx;
    155     while(scanf("%I64d%I64d%I64d",&k, &m, &newx)!=EOF){
    156         vector<LL> ans;
    157         ans = residue(m,k,newx);
    158         printf("case%d:
    ",++cas);
    159         if(ans.size()==0) puts("-1");
    160         for(int i = 0; i < ans.size(); ++i)
    161             printf("%I64d
    ",ans[i]);
    162     }
    163     return 0;
    164 }
  • 相关阅读:
    我喜欢的乐队-Descending
    SQL合并时间段的问题
    基本字符串相关函数,基本宏,内存相关函数,类型转换函数实现合集
    centos7.4 安装 .net core 2.2
    在Global.asax中 注册Application_Error事件 捕获全局异常
    一般后台系统数据库 用户权限设计
    API接口利用ActionFilterAttribute实现接口耗时检测
    Git 一般性操作
    tasks.json 配置 解决vscode控制台乱码问题
    iview发布到IIS 路由问题
  • 原文地址:https://www.cnblogs.com/aininot260/p/9709283.html
Copyright © 2020-2023  润新知