luogu P2485 [SDOI2011]计算器

题目描述

你被要求设计一个计算器完成以下三项任务:

1、给定y、z、p,计算y^z mod p 的值;

2、给定y、z、p,计算满足xy ≡z(mod p)的最小非负整数x;

3、给定y、z、p,计算满足y^x ≡z(mod p)的最小非负整数x。

为了拿到奖品,全力以赴吧!

输入输出格式

输入格式:

输入文件calc.in 包含多组数据。

第一行包含两个正整数T、L,分别表示数据组数和询问类型(对于一个测试点内的所有数

据,询问类型相同)。

以下T 行每行包含三个正整数y、z、p,描述一个询问。

输出格式:

输出文件calc.out 包括T 行.

对于每个询问,输出一行答案。

对于询问类型2 和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”。

输入输出样例

输入样例#1:
3 1
2 1 3
2 2 3
2 3 3
输出样例#1:
2
1
2
输入样例#2:
3 2
2 1 3
2 2 3
2 3 3
输出样例#2:
2
1
0
输入样例#3:
4 3
2 1 3
2 2 3
2 3 3
2 4 3
输出样例#3:
0
1
Orz, I cannot find x!
0

说明

本蒟蒻调了一下午样例,一个都没过

然后交上去ac,

突然意识到windows的 lld 和 I64d似乎从来没准过,orz orz 并且快速幂不知道怎么也写炸了

第一问,水 快速幂+mod

第二问,可用exgcd求,

当z为gcd(a,p)的倍数时才有解。

第三问,用bsgs(拔山盖世)求的是离散对数

具体可以自行百度。

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

 

posted @ 2017-05-17 17:53  zzzzx  阅读(213)  评论(0编辑  收藏  举报