【bzoj2242】[SDOI2011]计算器 EXgcd+BSGS
生活随笔
收集整理的這篇文章主要介紹了
【bzoj2242】[SDOI2011]计算器 EXgcd+BSGS
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目描述
你被要求設(shè)計(jì)一個(gè)計(jì)算器完成以下三項(xiàng)任務(wù): 1、給定y,z,p,計(jì)算Y^Z Mod P 的值; 2、給定y,z,p,計(jì)算滿足xy≡ Z ( mod P )的最小非負(fù)整數(shù); 3、給定y,z,p,計(jì)算滿足Y^x ≡?Z ( mod P)的最小非負(fù)整數(shù)。輸入
輸入包含多組數(shù)據(jù)。
第一行包含兩個(gè)正整數(shù)T,K分別表示數(shù)據(jù)組數(shù)和詢問(wèn)類型(對(duì)于一個(gè)測(cè)試點(diǎn)內(nèi)的所有數(shù)據(jù),詢問(wèn)類型相同)。 以下行每行包含三個(gè)正整數(shù)y,z,p,描述一個(gè)詢問(wèn)。輸出
對(duì)于每個(gè)詢問(wèn),輸出一行答案。對(duì)于詢問(wèn)類型2和3,如果不存在滿足條件的,則輸出“Orz, I cannot find x!”,注意逗號(hào)與“I”之間有一個(gè)空格。樣例輸入
【樣例輸入1】
3 1
2 1 3
2 2 3
2 3 3
【樣例輸入2】
3 2
2 1 3
2 2 3
2 3 3
樣例輸出
【樣例輸出1】
2
1
2
【樣例輸出2】
2
1
0
題解
EXgcd+BSGS
第一問(wèn)直接快速冪。
第二問(wèn)需要將xy≡z(mod p)轉(zhuǎn)化為xy+tp=z,進(jìn)而用EXgcd求解。
第三問(wèn)是裸的BSGS。
根據(jù)費(fèi)馬小定理可知如果有解,答案一定小于p。
設(shè)m=√p(向上取整),再設(shè)x=km+b,其中k<m,b<m。
那么就有y^(km+b)≡z(mod p),即y^b≡z/y^km(mod p)。
于是我們可以將所有的y^b mod p加入到map中,然后枚舉k,求出z/y^km,看是否有相同的值在map中即可。
本題特判比較多,具體詳見(jiàn)代碼。
#include <cstdio> #include <cmath> #include <map> using namespace std; typedef long long ll; map<ll , ll> f; map<ll , ll>::iterator it; ll pow(ll x , ll y , ll mod) {ll ans = 1;while(y){if(y & 1) ans = ans * x % mod;x = x * x % mod , y >>= 1;}return ans; } ll gcd(ll a , ll b) {return b ? gcd(b , a % b) : a; } void exgcd(ll a , ll b , ll &x , ll &y) {if(!b){x = 1 , y = 0;return;}exgcd(b , a % b , x , y);ll t = x;x = y , y = t - a / b * y; } int main() {int T , k;scanf("%d%d" , &T , &k);while(T -- ){ll y , z , p;scanf("%lld%lld%lld" , &y , &z , &p);switch(k){case 1: printf("%lld\n" , pow(y , z , p)); break;case 2:{y %= p , z %= p; ll t = gcd(y , p) , x1 , x2;if(z % t != 0){printf("Orz, I cannot find x!\n");break;}y /= t , p /= t , z /= t , exgcd(y , p , x1 , x2) , x1 *= z;while(x1 < 0) x1 += p;while(x1 - p >= 0) x1 -= p;printf("%lld\n" , x1);break;}default:{y %= p , z %= p; if(!y){if(!z) printf("1\n");else printf("Orz, I cannot find x!\n");break;}ll m = (ll)ceil(sqrt(p)) , i , flag = 0 , t = 1 , temp;f.clear();for(i = 0 ; i < m ; i ++ ){if(f.find(t) == f.end()) f[t] = i;t = t * y % p;}temp = pow(y , p - m - 1 , p) , t = 1;for(i = 0 ; i <= m ; i ++ ){it = f.find(z * t % p) , t = t * temp % p;if(it != f.end()){printf("%lld\n" , i * m + it->second) , flag = 1;break;}}if(!flag) printf("Orz, I cannot find x!\n");}}}return 0; }?
?
轉(zhuǎn)載于:https://www.cnblogs.com/GXZlegend/p/6999367.html
總結(jié)
以上是生活随笔為你收集整理的【bzoj2242】[SDOI2011]计算器 EXgcd+BSGS的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 瑞芯微芯片怎么样 AI芯片仅次于海思
- 下一篇: Visual Studio 中指定自定义