BZOJ 2242([SDOI2011]计算器-Baby Step Giant Step第1题)

来源:互联网 发布:linux 网卡不挂载驱动 编辑:程序博客网 时间:2024/05/24 05:58

2242: [SDOI2011]计算器

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 744  Solved: 289
[Submit][Status]

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

HINT

Source

第一轮day1

[Submit][Status]

第一次写这么【高端,洋气,上档次】的Hash

为特例苦调一下午……数论题写的根数据结构题还久……

Baby Step Giant Step+离散对数 可A此题

问:y^x=b (mod p) 求x

Hash暴力做法(和双向广搜类似)

事先处理出y^0,y^1....y^m

y^(im+j)= b (mod p)

y^im= b*y^j (mod p) 尽情暴力

注意特判:我参考的是lyd的程序


#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<functional>#include<cmath>#include<cctype>#include<map>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define ForD(i,n) for(int i=n;i;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define RepD(i,n) for(int i=n;i>=0;i--)#define MEM(a) memset(a,0,sizeof(a))#define MEMI(a) memset(a,127,sizeof(a))#define MEMi(a) memset(a,128,sizeof(a))#define INF (2139062143)#define MAXT (10+10)#define MAXY (1000000000)#define MAXN (1865060)typedef long long ll;ll gcd(ll a,ll b){if (!b) return a;return gcd(b,a%b);}ll exgcd(ll a,ll b,ll &x, ll &y){if (!b) {x=1,y=0;return a;}ll g=exgcd(b,a%b,x,y);ll t=x;x=y;y=t-a/b*y;return g;}ll pow2(ll a,int b,ll F){if (b==0) return 1;if (b==1) return a;ll c=pow2(a,b/2,F);c=c*c%F;if (b&1) c=c*a%F;return c;}void Modp(ll a,ll b,ll p){ll x,y;ll g=exgcd(a,p,x,y),d;if (b%g) {puts("Orz, I cannot find x!");return;}d=b/g;x*=d,y*=d;x=(x+abs(x)/p*p+p)%p;printf("%lld\n",x);}int h[MAXN]={0};ll hnum[MAXN]={0};int hash(ll x){int i=x%MAXN;while (h[i]&&hnum[i]!=x) i=(i+1)%MAXN;hnum[i]=x;return i;}void babystep(ll a,ll b,int p){int m=sqrt(p);while (m*m<p) m++;ll res=b,ans=-1;ll uni=pow2(a,m,p);if (!uni) if (!b) ans=1;else ans=-1; //特判else{Rep(i,m+1){int t=hash(res);h[t]=i+1;res=(res*a)%p;}res=uni;For(i,m+1){int t=hash(res);if (h[t]) {ans=i*m-(h[t]-1);break;}else hnum[t]=0;res=res*uni%p;}res=b;Rep(i,MAXN) h[i]=hnum[i]=0;}if (ans>-1) printf("%lld\n",ans);else puts("Orz, I cannot find x!");}int main(){//freopen("bzoj2242.in","r",stdin);//freopen("bzoj2242.out","w",stdout);int T,p,x,y,z;while (scanf("%d%d",&T,&p)==2){if (p==1){For(i,T){scanf("%d%d%d",&x,&y,&z);printf("%lld\n",pow2(x,y,z));}}else if (p==2){For(i,T){scanf("%d%d%d",&x,&y,&z);Modp(x,y%z,z);}}else{For(i,T){scanf("%d%d%d",&x,&y,&z);babystep(x,y%z,z);}}}return 0;}