日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bzoj3122 [Sdoi2013]随机数生成器(bsgs+扩欧+数列)

發布時間:2023/12/9 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj3122 [Sdoi2013]随机数生成器(bsgs+扩欧+数列) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

Input

輸入含有多組數據,第一行一個正整數T,表示這個測試點內的數據組數。

接下來T行,每行有五個整數p,a,b,X1,t,表示一組數據。保證X1和t都是合法的頁碼。

注意:P一定為質數

Output

共T行,每行一個整數表示他最早讀到第t頁是哪一天。如果他永遠不會讀到第t頁,輸出-1。

Sample Input
3
7 1 1 3 3
7 2 2 2 0
7 2 2 2 1

Sample Output
1
3
-1

HINT
0<=a<=P-1,0<=b<=P-1,2<=P<=10^9

分析:
剛剛學了數列,看到這道題就不那么難受了

X[i+1]=(aX[i]+b)mod p
X[i+1]+u=a(X[i]+u)
(a-1)u=b
u=b/(a-1)
X[i+1]+u=(X[1]+u)*a^i
a^i=(X[i+1]+u)/(X[1]+u) (mod p)
已知X[i+1]
實際上就是
x^i=z (mod p),求解最小i

最后答案就是i+1

然而這只適用于a!=1的情況

當a==1的時候
這就是一個等差數列了
X[i+1]=X[1]+b*i
X[i+1]-X[1]=b*i
設x=i,z=X[i+1]-X[1]
式子就可以化簡成
b*i=z (mod p)
b*i+k*p=z
我們先用擴歐求解b*i+k*p=1
最后把答案*z+1就可以了

注意

如果z不是gcd(b,p)的倍數,那么無解

一開始我的算法是:
i=(X[i+1]-X[1])*inv(b)
但是這樣秒WA,我覺得一概是無法判斷無解導致的

注意:p一定為質數
這樣求逆元就可以用費馬小定理了

tip

注意特殊情況的特判
x1==t,ans=1
a==0&&b==t,ans=2
a==0&&b!=t,ans=-1

一直連WA,最后才發現是主程序的問題
一個輸出后忘了回車!!!

這里寫代碼片 #include<cstdio> #include<iostream> #include<cstring> #include<map> #include<cmath> #define ll long longusing namespace std;map<ll,int> mp; ll p,z,t,x1,a,b,x,y;ll gcd(ll a,ll b) {ll r=a%b;while (r){a=b;b=r;r=a%b;}return b; }ll KSM(ll a,ll b,ll p) {a%=p;ll t=1;while (b){if (b&1)t=(t%p*a%p)%p;b>>=1;a=(a%p*a%p)%p;}return t%p; }int bsgs(ll x,ll z,ll p) {mp.clear();x%=p; z%=p;if (x==0&&z==0) return 2;if (x==0) return -1;ll m=(ll)ceil(sqrt((double)p)),now=1;mp[1]=m+1;for (int i=1;i<m;i++){now=(now%p*x%p)%p;if (!mp[now]) mp[now]=i;}ll inv=1,tmp=KSM(x,p-m-1,p);for (int k=0;k<m;k++){int i=mp[(z%p*inv%p)%p];if (i){if (i==m+1) i=0;return k*m+i+1;}inv=(inv%p*tmp%p)%p;}return -1; }void exgcd(ll a,ll b) {if (b==0){x=1; y=0;return;}else{exgcd(b,a%b);int tt=y;y=x-(a/b)*y;x=tt;} }ll inv(ll a,ll p) {return KSM(a,p-2,p); }int main() {int T;scanf("%d",&T);while (T--){scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);if (x1==t){printf("1\n");continue;} else if (a==0){if (b==t) printf("2\n");else printf("-1\n");continue;}else if (a==1) //等差數列 {z=((t-x1)%p+p)%p;if (z%gcd(b,p)!=0){printf("-1\n");continue;}exgcd(b,p);x=(x%p*z%p)%p;printf("%lld\n",(x%p+p)%p+1);}else //等比 {ll u=(b%p*inv(a-1,p)%p)%p; //u=b/(a-1)t=(t%p+u%p)%p; x1=(x1%p+u%p)%p;z=(t%p*inv(x1,p)%p)%p; //(X[i+1]+u)/(X[1]+u)printf("%d\n",bsgs(a,z,p));}}return 0; }

轉載于:https://www.cnblogs.com/wutongtong3117/p/7673239.html

總結

以上是生活随笔為你收集整理的bzoj3122 [Sdoi2013]随机数生成器(bsgs+扩欧+数列)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。