1 #include<cstdio>
  2 #include<iostream>
  3 #include<map>
  4 #include<cmath>
  5 #define ll long long
  6 using namespace std;
  7 ll T,k,y,z,p;
  8 map<int,int> mp;
  9 void exgcd(int a1,int a2,ll &x,ll &y)
 10 {
 11     if(!a2)
 12       {
 13         x=1;
 14         y=0;
 15         return;
 16       }
 17     exgcd(a2,a1%a2,x,y);
 18     int t=x;
 19     x=y;
 20     y=t-a1/a2*y;
 21 }
 22 ll gcd(ll a1,ll a2)
 23 {
 24     for(;a2;)
 25       {
 26         ll a3=a1%a2;
 27         a1=a2;
 28         a2=a3;
 29       }
 30     return a1;
 31 }
 32 ll kuai(ll y,ll z)
 33 {
 34     ll ans=1;
 35     for(;z;)
 36       {
 37         if(z%2)
 38            ans=(ans*y)%p;
 39         y=(y*y)%p;
 40         z=z/2;
 41       }
 42     return ans;
 43 }
 44 bool pan(ll y,ll z,ll p)
 45 {
 46     mp.clear();
 47     ll m=ceil(sqrt(p)),t=1;
 48     mp[1]=m+1;
 49     for(ll i=1;i<m;i++)
 50         {
 51            t=t*y%p;
 52            mp[t]=i;
 53         }
 54     ll T=kuai(y,p-m-1),ine=1;
 55     for(int k=0;k<=m;k++)
 56        {
 57            int i=mp[z*ine%p];
 58            if(i)
 59               {
 60                 if(i==m+1)
 61                   i=0;
 62                 printf("%lld\n",k*m+i);
 63                 return 1;
 64               } 
 65           ine=ine*T%p;
 66        }
 67     return 0;
 68 }
 69 int main()
 70 {
 71     scanf("%lld%lld",&T,&k);
 72     for(int i=1;i<=T;i++)
 73       {
 74         scanf("%lld%lld%lld",&y,&z,&p);
 75         if(k==1)
 76           printf("%lld\n",kuai(y,z));
 77         if(k==2)
 78           {
 79             ll x1,y1;
 80             ll t=gcd(y,p);
 81             if(z%t)
 82               {
 83                   printf("Orz, I cannot find x!\n");
 84                   continue;
 85               }
 86             y/=t;
 87             p/=t;
 88             z/=t;
 89             exgcd(y,p,x1,y1);
 90             x1=(x1*z)%p;
 91             for(;x1<0;)
 92               x1+=p;
 93             printf("%lld\n",x1);
 94           }
 95         if(k==3) 
 96           {
 97             y%=p;
 98             z%=p;
 99             if(!y&&!z)
100               {
101                 printf("1\n");
102                 continue;
103               }
104             if(!y)
105               {
106                   printf("Orz, I cannot find x!\n");
107                   continue;
108               }
109           if(!pan(y,z,p))
110             printf("Orz, I cannot find x!\n"); 
111           }
112       }
113     return 0;
114 }

第一种情况 快速幂  第二种情况 exgcd 第三种情况 大步小步法 把x变成k*m+i,把所有的0-m次方用map存下来,然后依次累加k,直到找到一个可行的。

posted on 2016-03-20 19:32  xiyuedong  阅读(153)  评论(0编辑  收藏  举报