bzoj2242 [SDOI2011]计算器

来源:互联网 发布:淘宝手机优惠券尺寸 编辑:程序博客网 时间:2024/06/07 07:17

题目传送:http://www.lydsy.com/JudgeOnline/problem.php?id=2242

题解:

对于1,直接快速幂

对于2,变形为X=Z/Y mod P 直接求Y的逆元,X=Z*inv[Y] mod P

对于3,裸的BSGS

附BSGS算法详解:

假如式子是A^x=B(mod C)

令m=sqrt(C) (m是int)

预处理出A^i mod C (i=0~m)并且建立一个哈希表(可以用map),hash[A^i]=i

令x=m*i+j,那么A^m^i * A^j = B (mod C)

枚举i,令t=A^m^i,那么t * A^j = B (mod C),

即A^j = B / t (mod C)

求出A^j,然后 hash查表得到j

如果j存在,那么ans=i*m+j为答案

否则继续进行,如果i从0到m枚举完还没发现解,则输出无解

代码:

//CodeVS1565 bzoj2242 [SDOI2011]计算器#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <map>#define ll  long longusing namespace std;ll A, B, C, M, T, L;map<ll,ll> hash;ll fastpow(ll a, ll b, ll p){ll ans, t;for(ans=1,t=a;b;b>>=1,t=t*t%p)if(b&1)ans=ans*t%p;return ans;}ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}void exgcd(ll a, ll b, ll &x, ll &y){if(a%b==0){x=0,y=1;return;}ll xx, yy;exgcd(b,a%b,xx,yy);x=yy;y=xx-a/b*yy;}ll inv(ll a, ll p){ll x, y;exgcd(a,p,x,y);return (x%p+p)%p;}ll gethash(){hash.clear();ll t, i;for(i=0,t=1;i<=M;i++,t=t*A%C)hash[t]=i;}ll BSGS(){ll d, i, j, Am, t, Aj, k;map<ll,ll>::iterator it;M=(ll)sqrt(C);gethash();Am=fastpow(A,M,C);if(!Am)return -1;for(i=0;i<=M;i++){Aj=B*inv(fastpow(Am,i,C),C)%C;it=hash.find(Aj);if(it!=hash.end())return M*i+it->second;}return -1;}int main(){ll ans;while(~scanf("%lld%lld",&T,&L)){while(T-->0){scanf("%lld%lld%lld",&A,&B,&C);if(L==1)ans=fastpow(A,B,C);if(L==2){if(A%C==0&&B!=0)ans=-1;else ans=B*inv(A,C)%C;}if(L==3)ans=BSGS();if(ans==-1)printf("Orz, I cannot find x!\n");else printf("%lld\n",ans);}}return 0;}


0 0
原创粉丝点击