标签:isp line 过程 scanf class 细节 fine ref https
求解关于x的方程
a ^ x Ξ b (mod p)
a ^ (p-1) Ξ 1 (mod p)
若x大于等于p-1
则a^xΞa^(p-1) * a^(x-p+1)Ξa^(x-p+1)
故x小于p-1
又m=√p
故i从1到m
得证
2.为什么bsgs在跳步过程中没有漏解
原因:在枚举i的过程中,看似是跳过了好多情况,但是其实在计算了每一个i之后,都会去map里面找每一个j去对应,相当于是将每一个i所对应的余数(剩余系)都枚举了一遍,即枚举了一遍完整的x的范围(因为x=i*m-j)。
#include<bits/stdc++.h> #define ll long long using namespace std; ll t,k,y,z,p; map<ll,ll>a; ll fpow(ll a,ll b,ll p) { ll ret=1; while(b) { if(b&1) ret=(ret*a)%p; b>>=1; a=(a*a)%p; } return ret; } void exgcd(ll a,ll b,ll &gcd,ll &xx,ll &yy) { if(!b) { xx=1,yy=0; gcd=a; return; } exgcd(b,a%b,gcd,xx,yy); ll tr=xx; xx=yy; yy=tr-a/b*yy; } int main() { cin>>t>>k; if(k==1) { while(t--) { scanf("%lld%lld%lld",&y,&z,&p); printf("%lld\n",fpow(y,z,p)); } } else if(k==2) { while(t--) { scanf("%lld%lld%lld",&y,&z,&p); ll gcd,xx,yy; exgcd(y,p,gcd,xx,yy); if(z%gcd!=0) printf("Orz, I cannot find x!\n"); else { xx*=z/gcd; xx%=(p/gcd); printf("%lld\n",(xx+(p/gcd))%(p/gcd)); } } } else { while(t--) { scanf("%lld%lld%lld",&y,&z,&p); ll m=ceil(sqrt(p)); if(y%p==0&&z) {printf("Orz, I cannot find x!\n");continue;}; a.clear(); ll now=z%p,f=fpow(y,m,p); a[now]=0; for(ll i=1;i<=m;i++) { now=(now*y)%p; a[now]=i; } now=1; ll flag=0; for(ll i=1;i<=m;i++) { now=(now*f)%p; if(a[now]) { ll ans=(i*m-a[now])%p; printf("%lld\n",(ans+p)%p); flag=1; break; } } if(!flag) printf("Orz, I cannot find x!\n"); } } return 0; }
ps.不开long long见祖宗可还行
标签:isp line 过程 scanf class 细节 fine ref https
原文地址:https://www.cnblogs.com/oierglh/p/11234686.html