zoukankan      html  css  js  c++  java
  • 计时器 【扩展欧几里得+BSGS】

    题目:

      https://www.luogu.org/problemnew/show/P2485

    题目简介:

      你被要求设计一个计算器完成以下三项任务:

      1、给定y、z、p,计算y^z mod p 的值;

      2、给定y、z、p,计算满足xy ≡z(mod p)的最小非负整数x;

      3、给定y、z、p,计算满足y^x ≡z(mod p)的最小非负整数x。

      为了拿到奖品,全力以赴吧!

    题解:

      问题一: 二分快速幂

     1 ll Make(ll x,ll y,ll mod){
     2     if(y==0) return 1%mod;
     3     ll mid=y/2;
     4     ll ans=Make(x,mid,mod);
     5     ans=(ans*ans)%mod;
     6     if(y&1){ans=(ans*x)%mod;}
     7     return ans; 
     8 }
     9 void Next1(){
    10     Read(Y),Read(Z),Read(P);
    11     ll ans=Make(Y,Z,P);
    12     Write(ans);
    13     return ;
    14 }
    View Code

      问题二: 扩展欧几里得模板

     1 ll ExGcd(ll a,ll b,ll &x,ll &y){
     2     if(b==0) {
     3         x=1;
     4         y=0;
     5         return a;
     6     }
     7     ll res=ExGcd(b,a%b,y,x);
     8     y-=a/b*x;
     9     return res;
    10 }
    11 void Next2(){
    12     Read(Y),Read(Z),Read(P);
    13     ll x,y,res;
    14     if(Y==0 && Z!=0){
    15         printf("Orz, I cannot find x!
    ");
    16         return ;
    17     }
    18     res=ExGcd(Y,P,x,y);    
    19     if(Z%res){
    20         printf("Orz, I cannot find x!
    ");
    21         return ;
    22     }
    23     x=((Z/res*x%P)+P)%(P/res);
    24     Write(x);
    25     return ;
    26 }
    View Code

      问题三:BabyStepGiantStep 【BSGS】

        对于幂取模,直接硬来(枚举指数)时间复杂度是过不去的

      对于BSGS的理解:

        对于 y^x ≡ z (mod p)

        根据抽屉原理: y^(p+k) mod p 的值一定存在于 y^(1~p) mod p 中(因为mod p最多有p个值)

        所以我们的考虑范围也就从 inf 缩小到了 p,但,这仍然是不够的

        思考继续缩小考虑范围

        想到分治,讲y^(1~p)分解为A部分 y^(1~m)  和B部分 y^(m+1~p) 

        考虑两者间的连系

          对于B部分的y^j   j一定满足  j=x+k*m  (k*m 是为了保障x<m)

          那么y^j=y^x  *  y^(k*m)    

          也就是说我们需要运算的也就化为了m+(p-m)  (最坏情况)

          为了应对最坏情况选择 m=sqrt(p)

     实现方法(BSGS):

        根据前面分析,我们只需要预处理 y^(1~m) 的结果  (注意离散化储存)

        然后枚举 y^(k*m) 并通过 方程 : a*y^(k*m)+b*p=z  解出所需值 a  (即分析中的 y^x)

        而 a 若是预处理过的值,即找到了 原方程的解

     

     1 const int Hash=100003;
     2 int Tot;
     3 int F[Hash+5];
     4 struct data{
     5     ll to,cost;
     6     int next;
     7 }E[Hash*10];
     8 void Addl(int x,ll y,ll z){
     9     E[++Tot]=(data){y,z,F[x]};
    10     F[x]=Tot;
    11     return ;
    12 }
    13 int H(ll x){
    14     return abs(x)%Hash;
    15 }
    16 ll Updata(int op,ll x,ll z){
    17     int t=H(x);
    18     int i=F[t];
    19     while(i){
    20         if(E[i].to==x) return E[i].cost;
    21         i=E[i].next;
    22     }
    23     if(op==0) return 0;
    24     Addl(t,x,z);
    25     return 0;
    26 }
    27 void Next3(){
    28     Read(Y),Read(Z),Read(P);
    29     if(Z==1){
    30         putchar('0');putchar('
    ');
    31         return ; 
    32     }
    33     if(Y==0 || Y%P==0){
    34         printf("Orz, I cannot find x!
    ");
    35         return ;
    36     }
    37     Tot=0;
    38     ll tmp=1;
    39     memset(F,0,sizeof(F));
    40     
    41     int m=sqrt(P);
    42     if(m*m<P) m++;
    43     Updata(1,1,m+1);
    44     for(ll i=1;i<m;i++){
    45         tmp=(tmp*Y)%P;
    46         Updata(1,tmp,i);
    47     }
    48     tmp=(tmp*Y)%P;
    49     ll ok=1,x,y;
    50     for(ll i=0;i<m;i++){
    51         ll res=ExGcd(ok,P,x,y);
    52         ll need=(((Z/res*x)%P)+P)%(P/res);
    53         ll opi=Updata(0,need,0);
    54         if(opi>0){
    55             if(opi==m+1) opi=0;
    56             Write(opi+m*i);
    57             return ;
    58         }
    59         ok=(ok*tmp)%P;
    60     }
    61     printf("Orz, I cannot find x!
    ");
    62     return ;
    63 }
    部分代码

    总代码

      1 #include<cmath>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 using namespace std;
      8 typedef long long ll;
      9 int T,K;
     10 ll Y,Z,P;
     11 void Read(ll &x){
     12     x=0;
     13     char c=getchar();
     14     while(!isdigit(c)) c=getchar();
     15     while(isdigit(c)) x=x*10-'0'+c,c=getchar();
     16     return ;
     17 }
     18 ll Make(ll x,ll y,ll mod){
     19     if(y==0) return 1%mod;
     20     ll mid=y/2;
     21     ll ans=Make(x,mid,mod);
     22     ans=(ans*ans)%mod;
     23     if(y&1){ans=(ans*x)%mod;}
     24     return ans; 
     25 }
     26 void Write(ll x){
     27     int np=0;
     28     int s[500];
     29     while(x) s[++np]=x%10,x/=10;
     30     if(!np) s[++np]=0;
     31     while(np) putchar(s[np--]+'0');
     32     putchar('
    ');
     33     return ;
     34 }
     35 void Next1(){
     36     Read(Y),Read(Z),Read(P);
     37     ll ans=Make(Y,Z,P);
     38     Write(ans);
     39     return ;
     40 }
     41 ll ExGcd(ll a,ll b,ll &x,ll &y){
     42     if(b==0) {
     43         x=1;
     44         y=0;
     45         return a;
     46     }
     47     ll res=ExGcd(b,a%b,y,x);
     48     y-=a/b*x;
     49     return res;
     50 }
     51 void Next2(){
     52     Read(Y),Read(Z),Read(P);
     53     ll x,y,res;
     54     if(Y==0 && Z!=0){
     55         printf("Orz, I cannot find x!
    ");
     56         return ;
     57     }
     58     res=ExGcd(Y,P,x,y);    
     59     if(Z%res){
     60         printf("Orz, I cannot find x!
    ");
     61         return ;
     62     }
     63     x=((Z/res*x%P)+P)%(P/res);
     64     Write(x);
     65     return ;
     66 }
     67 const int Hash=100003;
     68 int Tot;
     69 int F[Hash+5];
     70 struct data{
     71     ll to,cost;
     72     int next;
     73 }E[Hash*10];
     74 void Addl(int x,ll y,ll z){
     75     E[++Tot]=(data){y,z,F[x]};
     76     F[x]=Tot;
     77     return ;
     78 }
     79 int H(ll x){
     80     return abs(x)%Hash;
     81 }
     82 ll Updata(int op,ll x,ll z){
     83     int t=H(x);
     84     int i=F[t];
     85     while(i){
     86         if(E[i].to==x) return E[i].cost;
     87         i=E[i].next;
     88     }
     89     if(op==0) return 0;
     90     Addl(t,x,z);
     91     return 0;
     92 }
     93 void Next3(){
     94     Read(Y),Read(Z),Read(P);
     95     if(Z==1){
     96         putchar('0');putchar('
    ');
     97         return ; 
     98     }
     99     if(Y==0 || Y%P==0){
    100         printf("Orz, I cannot find x!
    ");
    101         return ;
    102     }
    103     Tot=0;
    104     ll tmp=1;
    105     memset(F,0,sizeof(F));
    106     
    107     int m=sqrt(P);
    108     if(m*m<P) m++;
    109     Updata(1,1,m+1);
    110     for(ll i=1;i<m;i++){
    111         tmp=(tmp*Y)%P;
    112         Updata(1,tmp,i);
    113     }
    114     tmp=(tmp*Y)%P;
    115     ll ok=1,x,y;
    116     for(ll i=0;i<m;i++){
    117         ll res=ExGcd(ok,P,x,y);
    118         ll need=(((Z/res*x)%P)+P)%(P/res);
    119         ll opi=Updata(0,need,0);
    120         if(opi>0){
    121             if(opi==m+1) opi=0;
    122             Write(opi+m*i);
    123             return ;
    124         }
    125         ok=(ok*tmp)%P;
    126     }
    127     printf("Orz, I cannot find x!
    ");
    128     return ;
    129 }
    130 int main(){
    131     scanf("%d%d",&T,&K);
    132     while(T--)
    133     if(K==1) Next1();
    134     else if(K==2) Next2();
    135     else Next3(); 
    136     return 0;
    137 }
    Code

        

        

  • 相关阅读:
    DataAnnotations
    使用BizTalk实现RosettaNet B2B So Easy
    biztalk rosettanet 自定义 pip code
    Debatching(Splitting) XML Message in Orchestration using DefaultPipeline
    Modifying namespace in XML document programmatically
    IIS各个版本中你需要知道的那些事儿
    关于IHttpModule的相关知识总结
    开发设计的一些思想总结
    《ASP.NET SignalR系列》第五课 在MVC中使用SignalR
    《ASP.NET SignalR系列》第四课 SignalR自托管(不用IIS)
  • 原文地址:https://www.cnblogs.com/Aloyd/p/9296666.html
Copyright © 2011-2022 走看看