bzoj3122: [Sdoi2013]随机数生成器

来源:互联网 发布:无线传感器网络应用 编辑:程序博客网 时间:2024/06/08 05:54

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3122

我去。。做这道题快把我累死了。。

原递推式:


推导过程:


为啥复制粘贴过来画质变渣了。。

另外需要注意的一点就是在做除法的时候不能直接用逆元,

比如说(10p/2p)mod p 本来应该等于5,但是你用逆元的话就成了0,因此应该一上来先把分子分母中公共的p除尽,再用逆元

代码:

#include <cstdio>#include <map>#include <cmath>#define ll long longusing namespace std;map<ll,ll> hash;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 BSGS(ll A, ll B, ll p){ll i, j, m, t, Am, Aj;map<ll,ll>::iterator it;m=sqrt(p);hash.clear();for(i=0,t=1;i<=m;i++,t=(t*A)%p)if(hash.find(t)==hash.end())hash[t]=i;for(i=1,Am=1;i<=m;i++)Am=Am*A%p;if(Am==0)return -2;for(i=0,t=1;i<=m;i++,t=t*Am%p){Aj=B*inv(t,p)%p;it=hash.find(Aj);if(it!=hash.end())return m*i+it->second;}return -2;}int main(){ll x1, a, b, p, t, T, m, n, ans;while(~scanf("%lld",&T)){while(T-->0){scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);if(a==0){if(x1==t)ans=0;else if(b%p==t)ans=1;else ans=-2;}else if(a!=1){m=t*(a-1)+b;n=x1*(a-1)+b;while(m%p==0 and n%p==0 and m)m/=p,n/=p;ans=BSGS(a,m%p*inv(n,p)%p,p);if(n==0 and m==0)ans=0;}else if(b!=0){m=t-x1;n=b;while(m%p==0 and n%p==0 and m)m/=p,n/=p;m=(m%p+p)%p;ans=m*inv(n,p)%p;if(m==0 and n==0)ans=0;}else{if(x1==t)ans=0;else ans=-2;}printf("%lld\n",ans+1);}}return 0;}


0 0
原创粉丝点击