BSGS[bzoj2242][bzoj3122]
数论题。
操作一:直接快速幂就好了。
操作二:我用了exgcd,shy和lyz都喜欢欧拉函数。。。QAQ最后这块还写错了。
对于ax+by=gcd(a,b)的形式,我们可以把他们变成y'x+p'y=1,当方程同乘以gcd(y,p),解不变。
最后只要将解乘以倍数即可。
操作三:baby step giant step,意为先小步后大步。由费马小定理可得答案不会超过p,我们可以把答案X看作k*m+i的形式,显然当m=sqrt(p)时复杂度最优。预处理m以内的hash值存入map(今天发现map真是个好东西), 枚举k,因为ni(y^k*m)*z%p=y^i%p,当当前值存在于哈希表是,则说明找到一个合法k与合法i,计入答案。
此时有一个特殊情况,若当前hash值为一,即ni(y^k*m)===z(mod p),则i=0;
#include<cstdio> #include<map> #include<cmath> #include<algorithm> #define ll long long using namespace std; int x,y,z,p;ll xx,yy; map<ll,ll>hash; int gcd(int a,int b) { )return a; return gcd(b,a%b); } void exgcd(int a,int b,ll &x,ll &y) { ){ x=;y=;return; } exgcd(b,a%b,x,y);int t=x;x=y;y=t-a/b*y; } int ni(int m) { -m;ll tmp=,a=y; while(k) { ==) { tmp=(tmp*a)%p; } a=a*a%p;k=k/; } return tmp; } void solve2() { z=z%p;y=y%p; &&z==){printf("1\n");return;} ){printf("Orz, I cannot find x!\n");return;} hash.clear(); int m=ceil(sqrt(p)); hash[]=m+;ll e=; ;i<=m;i++) { e=(e*y)%p;if(!hash[e])hash[e]=i; } ll ans=-,tmp=;e=ni(m);ll T=e; ;i<m;i++) { if(hash[tmp*z%p]) { )ans=i*m;else ans=i*m+hash[tmp*z%p]; break; } tmp=tmp*T%p; } )printf("Orz, I cannot find x!\n");else printf("%lld\n",ans); } int main() { int cas,ty; scanf("%d%d",&cas,&ty); while(cas--) { scanf("%d%d%d",&y,&z,&p); ) { ,a=y; ) { ==){ tmp=(tmp*a)%p; } a=a*a%p;k=k/; } printf("%lld\n",tmp); }) { int x;if(y>p)x=gcd(y,p);else x=gcd(p,y); ) { xx=,yy=;y=y/x;z=z/x;p=p/x; if(y>p) exgcd(y,p,xx,yy);else exgcd(p,y,yy,xx); xx=xx*z%p; )xx+=p; printf("%lld\n",xx); }else printf("Orz, I cannot find x!\n"); }) { solve2(); } } }
bzoj2242
07/23
3122这道题其实hzw的博客里已经写的很详尽了,但是蒟蒻还是理解了好久。
可能数论题的每一步操作每一个特判都很精妙,也可能是个人题目做得太少TAT
if(x1==t){ printf("1\n");continue; } ) { if(b==t)printf("2\n");else printf("-1\n"); continue; }
首先这里开场的两个特判;
if(a==1)
{
printf("%d\n",calc1());
continue;
}
其次是判断a==1的情况,我有尝试把它删去试试,发现这样就wa了,因为求数列的时候a不能为1;
对于a==1的可行情况,xn=x1+(n−1)b===(同余)t,我们把x1移项,做一下exgcd(b,p,x,y),(当然还要判一下它们的gcd是否被t-x1整除的情况);当然别忘了x可能<0,当然也别忘了x+1(x==n-1)。
当a>2时,这时的确需要一些数学姿势!
通项公式(我不会推啊。。。只能请教班上的数竞大神了)
“告诉你x1的值,x2=ax1+b,……,Xn=a*Xn-1+b,a与b的值已知,求数列通项公式,只要用x1,a,b表示就行。”
Xn=a^(n−1)*x1+b*A(n−1)−1/a−1(mod p)=t...........不会latex啦
我们就可以这样做:把所有常数丢到右边,与a^(n-1)相关的留在左边,
设c为a−1的逆元设c为a−1的逆元 (x1+bc)an−1=bc+t(mod p)
此时需要注意的是,系数A=x1+bc,系数B=bc+t,它们都有可能大于p了,所以这时候还需要特判:(这道题特判好多)
1.如果系数A%p==0,那么B也要是p的倍数才行
2.设a^(n-1)=S,做一遍exgcd(A,p,x,y),要求Ax+py=B嘛,只要乘以系数就好了,另外得到的x就可以代入BSGS了
好了。。。。。。。。干了这么多事情
终于可以用上窝萌亲爱的baby step giant step了!
第二遍写了,蛮好理解的...map蛮好用的+2
#include<cstdio> #include<map> #include<cmath> #include<algorithm> #define ll long long using namespace std; int cas; ll p,a,b,x1,t,x,y; ll quick(ll x,ll b) { x=x%p; ll k=b,tmp=,a=x; ) { ==) { tmp=tmp*a%p; } a=a*a%p;k/=; } return tmp; } ll exgcd(ll a,ll b,ll &x,ll &y) { ){ x=;y=;return a; } ll tmp=exgcd(b,a%b,x,y); ll t=x;x=y;y=t-a/b*y; return tmp; } ll calc1() { ll C=(t-x1+p)%p,x,y; ll day=exgcd(b,p,x,y); ; C/=day; x=x*C%p; )x+=p; ; } map<ll,int>mp; ll bsgs(ll A,ll B,ll C) { A%=C; ) { );;//MARK } ; ll t=,I=,Im=quick(A,C--m); mp.clear();mp[]=m+; ;i<m;i++) { t=t*A%C;if(!mp[t])mp[t]=i; } ;k<m;k++) { int i=mp[B*I%C]; if(i) { )i=;//printf("%d %d %lld\n",k,m,B); return m*k+i; } I=I*Im%C; } ; } ll calc2() { ll c=quick(a-,p-); ll C=(t+b*c)%p; ll A=(x1+b*c)%p; ll t=exgcd(A,p,x,y); ; C/=A; if(x<p)x=x%p+p; t=bsgs(a,x*C%p,p); //printf("===%lld\n",t); );; } int main() { scanf("%d",&cas); while(cas--) { scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t); if(x1==t){ printf("1\n");continue; } ) { if(b==t)printf("2\n");else printf("-1\n"); continue; } ) { printf("%d\n",calc1()); continue; } printf("%lld\n",calc2()); } }
bzoj3122
BSGS[bzoj2242][bzoj3122]的更多相关文章
- (ex)BSGS题表
学了一下BSGS大概知道他是什么了,但是并没有做什么难题,所以也就会个板子.普通的BSGS,我还是比较理解的,然而exBSGS我却只理解个大概,也许还会个板子......(这个东西好像都会有一群恶心的 ...
- 【BZOJ2242】计算器(BSGS,快速幂)
[BZOJ2242]计算器(BSGS,快速幂) 题面 BZOJ 洛谷 1.给定y.z.p,计算y^z mod p 的值: 2.给定y.z.p,计算满足xy ≡z(mod p)的最小非负整数x: 3.给 ...
- 【BZOJ3122】随机数生成器(BSGS,数论)
[BZOJ3122]随机数生成器(BSGS,数论) 题面 BZOJ 洛谷 题解 考虑一下递推式 发现一定可以写成一个 \(X_{i+1}=(X_1+c)*a^i-c\)的形式 直接暴力解一下 \(X_ ...
- 【BZOJ3122】[Sdoi2013]随机数生成器 BSGS+exgcd+特判
[BZOJ3122][Sdoi2013]随机数生成器 Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数. 接下来T行,每行有五个整数p,a,b, ...
- 【BZOJ2242】[SDOI2011]计算器 BSGS
[BZOJ2242][SDOI2011]计算器 Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ ...
- 【bzoj3122】: [Sdoi2013]随机数生成器 数论-BSGS
[bzoj3122]: [Sdoi2013]随机数生成器 当a>=2 化简得 然后 BSGS 求解 其他的特判 : 当 x=t n=1 当 a=1 当 a=0 判断b==t /* http: ...
- 【bzoj2242】: [SDOI2011]计算器 数论-快速幂-扩展欧几里得-BSGS
[bzoj2242]: [SDOI2011]计算器 1.快速幂 2.扩展欧几里得(费马小定理) 3.BSGS /* http://www.cnblogs.com/karl07/ */ #include ...
- 【BZOJ-3122】随机数生成器 BSGS
3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1362 Solved: 531[Submit][Sta ...
- 【BZOJ2242】【SDoi2011】计算器 快速幂+EXGCD+BSGS
Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...
随机推荐
- HTML 表格垂直对齐方式
HTML表格标记教程(25):行的垂直对齐属性VALIGN在垂直方向上,可以设定行的对齐方式,分别有居上.居中.居下3种.基本语法<TR VALIGN="TOP">&l ...
- ios滑动手势全屏(这段代码实现了下一级控制器滑到上一级控制器)
在自定义导航控制器里面加以下代码就增加全屏滑动手势 >推向前一个控制器 // HBNavigationController.m // #import "HBNavigationCon ...
- javascript void运算符
参考链接:http://www.cnblogs.com/ziyunfei/archive/2012/09/23/2698607.html语法: void expr 作用:计算表达式expr,并返回un ...
- main方法并发测试
public static void main(String[] args) throws Exception{ RequestModel r = new RequestModel(); r.setT ...
- 模拟赛1101d2
幸运数字(number)Time Limit:1000ms Memory Limit:64MB题目描述LYK 最近运气很差,例如在 NOIP 初赛中仅仅考了 90 分,刚刚卡进复赛,于是它决定使用一些 ...
- Eclipse主题更改
1. 直接安装color theme eclipse:Help->Install New Software->Work with:Update Site -http://eclipse-c ...
- DB2 上copy表结构及数据
现已有一行数据,要复制为多行,每行只有两个字段值不同,db2 没有sql server的top关键字,本只想复制几次,然后update逐条数据,发现不行. 然后想到不如临时创建一张表B,插入此行数据, ...
- NYOJ题目817英文藏头诗
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtEAAAKXCAIAAADLqoEhAAAgAElEQVR4nO3dO1LrzNbG8W8S5AyE2D
- ***CI的CLI运行方式
linux下的执行命令: 1.PHP解释器 2.CI根目录的index.php 3.控制器所在的文件夹 4. 控制器名称 5. 方法名称 (参数) 参考文献: http://codeigni ...
- Validform 学习笔记---代码练习
上一节主要梳理了validform的基础知识,针对这些基础知识,编写代码的时候,也整理的部分知识,先记录以便后期温习. 验证部分的css @charset "utf-8"; /* ...