博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ-2242 计算器 快速幂+拓展欧几里得+BSGS(数论三合一)
阅读量:5360 次
发布时间:2019-06-15

本文共 2376 字,大约阅读时间需要 7 分钟。

污污污污

2242: [SDOI2011]计算器

Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 2312 Solved: 917
[Submit][Status][Discuss]

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

第一问:快速幂直接搞;第二问:拓展欧几里得直接搞;第三问:BSGS直接搞;

安利一下BSGS的大体框架:

首先要求 a^x=b (mod c)
假定x=im-j (m=ceil(sqrt(n)))
那么进行变换:
a^im = b*a^j (mod c)
枚举b*a^j mod p的值存入哈希表(map)。
再枚举a^im的值,从哈希表里找,如果能找到一样的答案就是i*m-j

#include
#include
#include
#include
#include
#include
using namespace std;int n;int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f;}int gcd(int a,int b){ if (!b) return a; else return gcd(b,a%b);}void exgcd(int a,int b,int &x,int &y){ if (!b) {x=1,y=0;return;} exgcd(b,a%b,x,y); int t=x;x=y; y=t-a/b*y;}long long quick_pow(long long a,int b,int p)//返回a^b%p的值{ long long re=1; long long tmp=a%p; while (b) { if (b&1) re=(re*tmp)%p; tmp=(tmp*tmp)%p; b=b>>1; } return re;}void work1(int a,int b,int c) { printf("%lld\n",quick_pow(a,b,c));}void work2(int a,int b,int c) { c=-c; int gc=gcd(a,c); if (b%gc!=0) { puts("Orz, I cannot find x!");return;} a/=gc;b/=gc;c/=gc; int x,y;exgcd(a,c,x,y); x=(long long)x*b%c; while (x<0) x+=c; printf("%d\n",x);}void work3(int a,int b,int c){ map
mp;mp.clear(); if (a%c==0) { puts("Orz, I cannot find x!");return;} int m=ceil(sqrt(c)); long long t=b; for (int i=0; i<=m; i++) { mp[(int)t]=i; t=t*a%c; } int s=quick_pow(a,m,c);t=s; for (int i=1; i<=m; i++) { int v=mp[(int)t]; if (v!=0) { printf("%d\n",i*m-v);return;} t=t*s%c; } puts("Orz, I cannot find x!");}int main(){ int t=read(),k=read(); for (int i=1; i<=t; i++) { int y=read(),z=read(),p=read(); if (k==1) work1(y,z,p); if (k==2) work2(y,z,p); if (k==3) work3(y,z,p); } return 0;}

转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346201.html

你可能感兴趣的文章
java中new一个对象和对象=null有什么区别
查看>>
字母和数字键的键码值(keyCode)
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>
Spring mvc初学
查看>>
VTKMY 3.3 VS 2010 Configuration 配置
查看>>
01_1_准备ibatis环境
查看>>
windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决
查看>>
JavaScript中的BOM和DOM
查看>>
360浏览器兼容模式 不能$.post (不是a 连接 onclick的问题!!)
查看>>
spring注入Properties
查看>>
jmeter(五)创建web测试计划
查看>>
python基本数据类型
查看>>
1305: [CQOI2009]dance跳舞 - BZOJ
查看>>
将html代码中的大写标签转换成小写标签
查看>>
jmeter多线程组间的参数传递
查看>>
零散笔记
查看>>
信息浏览器从Android的浏览器中传递cookie数据到App中信息浏览器
查看>>
hash储存机制
查看>>
HI3531uboot开机画面 分类: arm-linux-Ubunt...
查看>>
制作U盘启动CDLinux 分类: 生活百科 ...
查看>>