您的位置:首页 > 其它

bzoj2242 [SDOI2011]计算器

2018-02-04 12:01 267 查看

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)的最小非负整数。

Solution

第一问瞎搞,第二问因为p是质数因此求一下逆元即可。如果不是质数的话可以考虑exgcd

第三问是BSGS

设x=ti−jx=ti−j,则Yti−j≡Z(modP)Yti−j≡Z(modP),移项得Yti≡ZYj(modP)Yti≡ZYj(modP)

可以先枚举j用map记录,然后枚举i判断是否存在一个ZYjZYj就ok。显然t取P−−√P比较优秀

证明:由YP−1≡1(modP)YP−1≡1(modP)可知这里存在一个循环,x最大取到p

洛谷能a但是bzoj死活过不了,难拍,留坑

Code

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <map>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

typedef long long LL;

std:: map <int, int> map;

LL ksm(LL x,int dep,int mod) {
if (dep==0) return 1;
if (dep==1) return x;
LL tmp=ksm(x,dep/2,mod);
if (dep%2) return tmp*tmp%mod*x%mod;
else return tmp*tmp%mod;
}

void solve1(int a,int b,int c) {
printf("%lld\n", ksm((LL)a,b,c)%c);
}

void solve2(int a,int b,int c) {
b=b%c;
if (a==0&&b!=0) {
puts("Orz, I cannot find x!");
return ;
}
LL ans=ksm(a,c-2,c)*(LL)b%c;
while (ans<0) ans=(ans+c)%c;
printf("%lld\n", ans);
}

void solve3(LL a,LL b,LL c) {
if (a+b==0) {
puts("1");
return ;
}
if (a+b==b) {
puts("Orz, I cannot find x!");
return ;
}
map.clear();
int m=(int)ceil(sqrt(c));
rep(i,0,m) {
int x=ksm(a,i,c)*b%c;
map[x]=i;
}
rep(i,1,m) {
LL x=ksm(a,m*i,c);
if (map[x]) {
LL ans=i*m-map[x];
while (ans<0) ans=(ans+c)%c;
printf("%lld\n", ans);
return ;
}
}
puts("Orz, I cannot find x!");
}

int main(void) {
int n,m; scanf("%d%d",&n,&m);
while (n--) {
LL a,b,c; scanf("%lld%lld%lld",&a,&b,&c);
a=a%c;
if (m==1) {
solve1(a,b,c);
} else if (m==2) {
solve2(a,b,c);
} else if (m==3) {
solve3(a,b,c);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: