bzoj 2242: [SDOI2011]计算器

垃圾SDOI,,,,,,,,,,,,,,,

前2问快速幂之类的玩意乱搞

第三问,是一个看起来就nb的BSGS(baby step giant step)算法,大概的意思是把指数y分块(大小为m),y=am+b,然后把其中的am或b移动到z的一边,那么每一边都只需要算根号y次,复杂度就降低了。(根据费马小定理,y最大只能取到p-1,(否则会进入循环节))

因为移项之后指数是负的,所以求一下逆元,(真费事)

(真是个sb题,里面的int,LL,,,各种各样的不对,****,WA一片)

 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 #define LL long long
 4 #define inf 0x3f3f3f3f
 5 using namespace std;
 6 inline LL ra()
 7 {
 8     LL x=0,f=1; char ch=getchar();
 9     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
10     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
11     return x*f;
12 }
13 int solve1(LL y,int z,int p)
14 {
15     y%=p;
16     LL ans=1;
17     for(int i=z;i;i>>=1,y=y*y%p)
18         if(i&1)ans=ans*y%p;
19     return ans;
20 }
21 void solve2(int y, int z, int p)
22 {
23     y%=p;
24     if (!y) {puts("Orz, I cannot find x!"); return; }
25     LL ans=(LL)solve1(y,p-2,p)*z%p;
26     printf("%d\n",(int)ans%p);
27 }
28 map<int,int> mp;
29 void solve3(int y, int z, int p)
30 {
31     y%=p;
32     if (!y && !z) {puts("1"); return;}
33     if (!y) {puts("Orz, I cannot find x!"); return;}
34     mp.clear();
35     LL m=ceil(sqrt(p)),t=1;
36     mp[1]=m+1;
37     for (LL i=1; i<m; i++)
38     {
39         t=t*y%p;
40         if (!mp[t]) mp[t]=i;
41     }
42     LL tmp=solve1(y,p-m-1,p),ine=1;
43     for (LL k=0; k<m; k++)
44     {
45         int i=mp[z*ine%p];
46         if (i)
47         {
48             if (i==m+1) i=0;
49             printf("%lld\n",k*m+i);
50             return;
51         }
52         ine=ine*tmp%p;
53     }
54     puts("Orz, I cannot find x!");
55 }
56 int main()
57 {
58     int T=ra(), K=ra();
59     while (T--)
60     {
61         LL y=ra(),z=ra(),p=ra();
62         if (K==1) printf("%d\n",solve1(y,z,p));
63         if (K==2) solve2(y,z,p);
64         if (K==3) solve3(y,z,p);
65     }
66     return 0;
67 }

 

posted @ 2017-02-23 20:39  ws_ccd  阅读(170)  评论(0编辑  收藏  举报