• BZOJ2242: [SDOI2011]计算器


    2242: [SDOI2011]计算器

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 1278  Solved: 492
    [Submit][Status]

    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”之间有一个空格。

    Sample Input

    【样例输入1】
    3 1
    2 1 3
    2 2 3
    2 3 3
    【样例输入2】
    3 2
    2 1 3
    2 2 3
    2 3 3
    【数据规模和约定】
    对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。

    Sample Output

    【样例输出1】
    2
    1
    2
    【样例输出2】
    2
    1
    0

    HINT

     

    Source

    题解:
    第一问快速幂,第二问拓展欧几里德,第三问shank的大步小步算法。
    算法基于这样的性质:
    若有 a^(k*m+i)=b (mod p)
    则有 a^i=b/(a^km) =b*(a^km)-1  (mod p) 其中-1 指 模p意义下的逆元
    如果 左边的i很少,我们就可以预处理出所有的 a^i,然后枚举k查询是否有 b*(a^km)-1这样的键值存在,存在的话答案就是 k*m+i.
    显然 m取sqrt(n)比较合适。
    枚举k时还有技巧就是a^km的逆元随着k的增加,不用每次都求,我们先求出a^m的逆元 t=power(a,p-m-1,p)
    这样每次k++,b*=t,这是因为 a^(p-m-1+p-m-1)=a^(p-2*m-1)*a^(p-1)=a^(p-m-1)。
    查询可以用map存储,也可以手写二分。
    bzoj的评测机太感人了,本地测50s+,在bzoj上居然1s就跑出来了,真是奇迹。
    代码:
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<iostream>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 #include<queue>
     11 #include<string>
     12 #define inf 1000000000
     13 #define maxn 500+100
     14 #define maxm 500+100
     15 #define eps 1e-10
     16 #define ll long long 
     17 #define pa pair<int,int>
     18 #define for0(i,n) for(int i=0;i<=(n);i++)
     19 #define for1(i,n) for(int i=1;i<=(n);i++)
     20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     21 using namespace std;
     22 typedef map<int,int>::const_iterator cit;
     23 typedef map<int,int>::value_type vt; 
     24 map<int,int> mp;
     25 inline ll read()
     26 {
     27     int x=0,f=1;char ch=getchar();
     28     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     29     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     30     return x*f;
     31 }
     32 ll a,b,p,x,y,t,tt,gcd,m,cs,ch;
     33 ll work1(ll a,ll b,ll p)
     34 {
     35     ll ans=1;
     36     for(;b;b>>=1,a*=a,a%=p)
     37      if(b&1)ans*=a,ans%=p;
     38     return ans; 
     39 }
     40 void exgcd(ll a,ll b)
     41 {
     42     if(!b){x=1;y=0;gcd=a;}
     43     else
     44      {
     45          exgcd(b,a%b);
     46          t=x;x=y;y=t-(a/b)*y;
     47      }
     48 }
     49 void work2()
     50 {
     51     exgcd(a,p);
     52     if(b%gcd)puts("Orz, I cannot find x!");
     53     else
     54      {
     55          x*=b/gcd;y*=b/gcd;
     56         t=p/gcd;
     57          x=(x%t+t)%t;
     58          printf("%lld
    ",x);
     59      }
     60 }
     61 void work3()
     62 {
     63     a%=p;b%=p;
     64     if(!a&&!b){printf("1
    ");return;}
     65     if(!a){puts("Orz, I cannot find x!");return;}
     66     m=floor(sqrt(p));
     67     mp.clear();
     68     mp.insert(mp.begin(),vt(1,0));
     69     t=1;
     70     for1(i,m-1)t*=a,t%=p,mp.insert(mp.begin(),vt(t,i));
     71     t=work1(a,p-m-1,p);
     72     for0(i,p/m)
     73      {
     74          cit j=mp.find(b);
     75          if(j!=mp.end())
     76          {
     77             printf("%lld
    ",j->second+i*m);
     78              return;
     79          }
     80         b*=t;b%=p; 
     81      }
     82      puts("Orz, I cannot find x!");
     83 }
     84 int main()
     85 {
     86     freopen("input.txt","r",stdin);
     87     freopen("output.txt","w",stdout);
     88     cs=read();ch=read();
     89     while(cs--)
     90      {
     91          a=read();b=read();p=read();
     92          switch(ch)
     93          {
     94              case 1:printf("%lld
    ",work1(a,b,p));break;
     95              case 2:work2();break;
     96              case 3:work3();break;
     97          }
     98      }
     99     return 0;
    100 }
    View Code
  • 相关阅读:
    索引yellow 分片 UNASSIGNED 解决方案1
    Linux zip压缩多文件
    查询数据库实例名,服务名,和oracle_sid
    excel2csv 多sheet拆分到不同csv
    创建按月自动分区表
    自动生成sequence
    oracle 11g 分区表创建(自动按年、月、日分区)
    linux 查找字符串
    Oracle 字符串截取和位置
    mongodb查询某个字段数据
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3960832.html
Copyright © 2020-2023  润新知