首页 > 代码库 > 【bzoj2242】[SDOI2011]计算器

【bzoj2242】[SDOI2011]计算器

2242: [SDOI2011]计算器

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 3207  Solved: 1258
[Submit][Status][Discuss]

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
 
 
【吐槽】
 
三合一的一道模板题。快速幂+扩展gcd+离散对数
 
学过这三个的人应该都会吧,不会的。。。传送门:http://www.cnblogs.com/chty/p/6022641.html
 
写的时候手贱把哈希表写错了,调了半天。。。
 
贴个丑陋的代码:
 
  1 /*************
  2   bzoj 2242
  3   by chty
  4   2016.11.9
  5 *************/
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<cstdlib>
  9 #include<cstring>
 10 #include<ctime>
 11 #include<cmath>
 12 #include<algorithm>
 13 using namespace std;
 14 #define FILE "read"
 15 #define MAXN 99991
 16 typedef long long ll;
 17 struct node{ll v,f,num;}hash[MAXN+10];
 18 ll a,b,mod;
 19 inline ll read()
 20 {
 21     ll x=0,f=1;  char ch=getchar();
 22     while(!isdigit(ch))  {if(ch==-)  f=-1;  ch=getchar();}
 23     while(isdigit(ch))  {x=x*10+ch-0;  ch=getchar();}
 24     return x*f;
 25 }
 26 void insert(ll v,ll x)
 27 {
 28     ll temp=v%MAXN;
 29     while(hash[temp].f&&hash[temp].v!=v) {temp++; if(temp>MAXN) temp-=MAXN;}
 30     if(!hash[temp].f) hash[temp].f=1,hash[temp].v=v,hash[temp].num=x;
 31 }
 32 ll find(ll v)
 33 {
 34     ll temp=v%MAXN;
 35     while(hash[temp].f&&hash[temp].v!=v) {temp++; if(temp>MAXN) temp-=MAXN;}
 36     if(!hash[temp].f)  return -1;
 37     else return hash[temp].num;
 38 }
 39 ll gcd(ll a,ll b) {return !b?a:gcd(b,a%b);}
 40 ll exgcd(ll a,ll b,ll &x,ll &y)
 41 {
 42     if(!b) {x=1; y=0; return a;}
 43     ll g=exgcd(b,a%b,x,y);
 44     ll t=x;x=y;y=t-a/b*y;
 45     return g;
 46 }
 47 void solve1(){ll sum=1;for(;b;b>>=1,a=a*a%mod)if(b&1)sum=sum*a%mod;printf("%d\n",sum);}
 48 void solve2()
 49 {
 50     ll x,y,d=exgcd(a,mod,x,y);
 51     if(b%d)  {printf("Orz, I cannot find x!\n");return;}
 52     ll t=mod/d;
 53     while(x<0)  x+=t;
 54     while(x>=t) x-=t;
 55     printf("%lld\n",x*b%mod);
 56 }
 57 void solve3()
 58 {
 59     if(mod==1)  {puts("0"); return;}
 60     a%=mod;b%=mod;
 61     ll ret(1);
 62     for(ll i=0;i<=50;i++) {if(ret==b) {printf("%lld\n",i); return; ret=ret*a%mod;}}
 63     ll temp,ans(1),cnt(0);
 64     while((temp=gcd(a,mod))!=1)
 65     {
 66         if(b%temp)  {printf("Orz, I cannot find x!\n");return;}
 67         mod/=temp;  b/=temp;
 68         ans=ans*(a/temp)%mod;
 69         cnt++;
 70     }
 71     ll m=(ll)sqrt(mod*1.0),t(1);
 72     for(ll i=0;i<m;i++)  {insert(t,i);t=t*a%mod;}
 73     for(ll i=0;i<m;i++)
 74     {
 75         ll x,y;
 76         exgcd(ans,mod,x,y);
 77         ll val=x*b%mod;
 78         val=(val+mod)%mod;
 79         ll j=find(val);
 80         if(j!=-1)  {printf("%lld\n",i*m+j+cnt);return;}
 81         ans=ans*t%mod;
 82     }
 83     printf("Orz, I cannot find x!\n");
 84     return;
 85 }
 86 void pre() {for(ll i=0;i<=MAXN;i++)hash[i].f=0,hash[i].num=hash[i].v=-1;}
 87 int main()
 88 {
 89     freopen(FILE".in","r",stdin);
 90     freopen(FILE".out","w",stdout);
 91     ll T=read(),flag=read();
 92     while(T--)
 93     {
 94         pre();
 95         a=read();  b=read();  mod=read();
 96         switch(flag)
 97         {
 98             case 1:solve1();break;
 99             case 2:solve2();break;
100             case 3:solve3();break;
101         }
102     }
103     return 0;
104 }

 

 

【bzoj2242】[SDOI2011]计算器