P2485 [SDOI2011]计算器

 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

说明

分析

三个模板,

  1. 快速幂,
  2. 求yx=z(mod p),转化成,yx-kp = z;可以用扩展欧几里得求解,并且要求z%gcd(y,p)!=0,(扩展欧几里得求ax+by=chttp://www.cnblogs.com/MashiroSky/p/5912977.html),         补充:因为p是质数,所以可以用费马小定理, p是质数,y与p互质,所以y有逆元,x=y^(-1)*z,y^(-1)=y^(p-2),因为0没有逆元,所以只有y=0时无解
  3. bsgs

注意,int与longlong类型,结尾的换行符

code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<map>
  4 #include<cmath>
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 map<int,int>mp;
  9 
 10 int ksm(int a,int p,int mod)
 11 {
 12     int now = 1;
 13     while (p)
 14     {
 15         if (p&1)
 16             now = 1ll*now*a%mod;
 17         a = 1ll*a*a%mod;
 18         p = p>>1;
 19     }
 20     return now;
 21 }
 22 int exgcd(int a,int b,int &x,int &y)
 23 {
 24     if (b==0)
 25     {
 26         x = 1, y = 0;
 27         return a;
 28     }
 29     int r = exgcd(b,a%b,x,y);
 30     int t = x;
 31     x = y;
 32     y = t-(a/b)*y;
 33     return r;
 34 }
 35 void bsgs(int a,int b,int p)
 36 {
 37     int m,t,ans,now;
 38     if (a%p==0&&b==0) 
 39     {
 40         printf("1\n");return ;
 41     }
 42     if (a%p==0) 
 43     {
 44         printf("Orz, I cannot find x!\n");return ;
 45     }
 46     mp.clear();
 47     m = ceil(sqrt(p));
 48     now = b%p;
 49     mp[now] = 0;
 50     for (int i=1; i<=m; ++i)
 51     {
 52         now = (1ll*now*a)%p;
 53         mp[now] = i;
 54     }
 55     t = ksm(a,m,p);
 56     now = 1;
 57     for (int i=1; i<=m; ++i)
 58     {
 59         now = (1ll*now*t)%p;
 60         if (mp[now])
 61         {
 62             ans = i*m-mp[now];
 63             printf("%d\n",(ans%p+p)%p);
 64             return ;
 65         }
 66     }
 67     printf("Orz, I cannot find x!\n");
 68 }
 69 int main()
 70 {
 71     int t,k,a,b,c;
 72     scanf("%d%d",&t,&k);
 73     if (k==1)
 74     {
 75         for (int i=1; i<=t; ++i)
 76             scanf("%d%d%d",&a,&b,&c),printf("%d\n",ksm(a,b,c));
 77     }
 78     else if (k==2)
 79     {
 80         int x,y;
 81         for (int i=1; i<=t; ++i)
 82         {
 83             scanf("%d%d%d",&a,&b,&c);
 84             int d = exgcd(a,c,x,y);
 85             if (b%d!=0) printf("Orz, I cannot find x!\n");    //换行符 
 86             else 
 87             {
 88                 x = 1ll*x*(b/d)%c;
 89                 x = (x%(c/d)+c/d)%(c/d);
 90                 printf("%d\n",x);
 91             }
 92         }
 93     }
 94     else
 95     {
 96         for (int i=1; i<=t; ++i)
 97             scanf("%d%d%d",&a,&b,&c),bsgs(a,b,c);
 98     }
 99     return 0;
100 }

 

posted @ 2017-08-08 08:00  MJT12044  阅读(341)  评论(0编辑  收藏  举报