BZOJ-2242 (幾種數論模板)

題目

2242: [SDOI2011]計算器
Time Limit: 10 Sec Memory Limit: 512 MB
Description

你被要求設計一個計算器完成以下三項任務:
1、給定y,z,p,計算Y^Z Mod P 的值;
2、給定y,z,p,計算滿足xy≡ Z ( mod P )的最小非負整數;
3、給定y,z,p,計算滿足Y^x ≡ Z ( mod P)的最小非負整數。

Input

輸入包含多組數據。

第一行包含兩個正整數T,K分別表示數據組數和詢問類型(對於一個測試點內的所有數據,詢問類型相同)。
以下行每行包含三個正整數y,z,p,描述一個詢問。

對於100%的數據,1<=y,z,p<=10^9,爲質數,1<=T<=10。

Output

對於每個詢問,輸出一行答案。對於詢問類型2和3,如果不存在滿足條件的,則輸出“Orz, I cannot find x!”,注意逗號與“I”之間有一個空格。

Sample Input

【樣例輸入1】

3 1
2 1 3
2 2 3
2 3 3

【樣例輸入2】

3 2
2 1 3
2 2 3
2 3 3

Sample Output

【樣例輸出1】

2
1
2

【樣例輸出2】

2
1
0

分析

  • 第一種詢問,直接快速冪;
  • 第二種,x=(Y/1)*Z,逆元一下再模一下(求出最小解);
  • 第三種,bsgs 求解即可。

程序

#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;
typedef long long ll;
ll m,T,K,Y,Z,P,k,F,G,ret,ss;
map <ll,ll> M;

ll ksm(ll x,ll y){
    for (ret=1; y; y>>=1,x=(x*x)%P)
        if (y&1) ret=(ret*x)%P;
    return ret;
}

int main(){
    scanf("%lld%lld",&T,&K);
    if (K==1){
        for (; T--; ){
            scanf("%lld%lld%lld",&Y,&Z,&P);
            printf("%lld\n",ksm(Y,Z));
        }
        return 0;
    }
    if (K==2){
        for (; T--; ){
            scanf("%lld%lld%lld",&Y,&Z,&P);
            Y%=P,Z%=P;
            if (Y==0 && Z!=0){puts("Orz, I cannot find x!"); continue;}
            k=(ksm(Y,P-2)*Z)%P;
            printf("%lld\n",k);
        }
        return 0;
    }
        for (; T--; ){
            scanf("%lld%lld%lld",&Y,&Z,&P);
            Y%=P,Z%=P;          //這裏要模夠 
            if (!Y && !Z){puts("1"); continue;}
            if (!Y){puts("Orz, I cannot find x!"); continue;}
            M.clear();
            m=ceil(sqrt(P));
            ss=Z%P; M[ss]=0;
            for (ll i=1; i<=m; i++){
                ss=(ss*Y)%P;
                if (!M[ss]) M[ss]=i;
            }
            G=ksm(Y,m);
            F=0,ss=1;
            for (ll i=1; i<=m && !F; i++){
                ss=(ss*G)%P;
                if (M[ss]){
                    ss=(i*m-M[ss]);
                    printf("%lld\n",(ss%P+P)%P);
                    F=1;
                    break;
                }
            }
            if (!F) puts("Orz, I cannot find x!");
        }
    return 0;
}

提示

  • 打註釋那裏要模,不然過不了,不知道爲什麼。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章