zoukankan      html  css  js  c++  java
  • 【数学 BSGS】bzoj2242: [SDOI2011]计算器

    数论的板子集合……

    Description

    你被要求设计一个计算器完成以下三项任务:
    1、给定y,z,p,计算Y^Z Mod P 的值;
    2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;
    3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。

    Input

     输入包含多组数据。

    第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
    以下行每行包含三个正整数y,z,p,描述一个询问。

    Output

    对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。

    题目分析

    第一个问题:快速幂解决

    第二个问题:1.转为exgcd问题   2.直接$x=Z*y^{-1}$

    第三个问题:BSGS

    BSGS是引入分块的思想解决形如$A^x≡B(mod\,C) C为素数$的问题(至于C不是素数就是exBSGS的范畴了)

    具体来说,就是记$size=sqrt C$,$x=i*size-j \, (0≤j<sqrt C)$,于是式子就成了$A^{i*size}≡A^j*B$的形式。而右边这个东西是可以预处理出来放在hash表里的,这样在$sqrt C$枚举$i$的过程中,就可以$O(1)/O(log \, n)$判断是否有相应的j了。

    这类思想挺妙的,应该可以迁移到其他地方。

     1 #include<bits/stdc++.h>
     2 typedef long long ll;
     3 
     4 int T,k;
     5 ll x,y,p,w,z,d,cir;
     6 std::map<ll, int> mp;
     7 
     8 ll qmi(ll a, ll b)
     9 {
    10     ll ret = 1;
    11     for (a%=p; b; b>>=1, a=a*a%p)
    12         if (b&1) ret = ret*a%p;
    13     return ret;
    14 }
    15 ll gcd(ll a, ll b){return !b?a:gcd(b, a%b);}
    16 void exgcd(ll a, ll b, ll &x, ll &y)
    17 {
    18     if (!b){
    19         x = 1, y = 0;
    20         return;
    21     }
    22     exgcd(b, a%b, y, x), y -= a/b*x;
    23 }
    24 ll BSGS(ll a, ll b, ll p)
    25 {
    26     if (((!b)&&(!a))) return 1;
    27     if ((!a)&&b) return -1;
    28     if (b==1) return 0;
    29     ll size = ceil(sqrt(p)), bse = 1;
    30     mp.clear();
    31     for (int i=0; i<size; i++)
    32     {
    33         mp[bse*b%p] = i;
    34         bse = bse*a%p;
    35     }
    36     for (ll i=0, now=1; i<=p; i+=size, now = now*bse%p)
    37         if (mp.count(now)) return ((i-mp[now])%p+p)%p;
    38     return -1;
    39 }
    40 int main()
    41 {
    42     for (scanf("%d%d",&T,&k); T; --T)
    43     {
    44         scanf("%lld%lld%lld",&x,&y,&p);
    45         if (k==1) printf("%lld
    ",qmi(x, y));
    46         if (k==2){
    47             x %= p, y %= p;
    48             if (!x) puts("Orz, I cannot find x!");
    49             else printf("%lld
    ",y*qmi(x, p-2)%p);
    50         }
    51         if (k==3){
    52             x %= p, y %= p, d = BSGS(x, y, p);
    53             if (d==-1) puts("Orz, I cannot find x!");
    54             else printf("%lld
    ",d);
    55         }
    56     }
    57     return 0;
    58 }

    END

  • 相关阅读:
    C++设计模式-Bridge桥接模式
    解决VS2010打开Web页面时经常由于内存较低而导致VS2010自动关闭的问题
    Js继承小结
    MAC上的包管理利器
    Objective-C的hook方案(一): Method Swizzling
    OleContainer操作Excel以二进制方式读写数据库
    复制文件时,如何显示进度条(使用TFileStream一点一点读,或者使用BlockRead,并插入application.ProcessMessages)
    ADO异步查询显示进度条
    D2010 RTTI + Attribute 简单实现ORM
    Delphi默认窗体随想
  • 原文地址:https://www.cnblogs.com/antiquality/p/10252340.html
Copyright © 2011-2022 走看看