結果
| 問題 |
No.981 一般冪乗根
|
| ユーザー |
|
| 提出日時 | 2021-01-22 17:41:52 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 2,647 ms / 6,000 ms |
| コード長 | 3,297 bytes |
| コンパイル時間 | 1,013 ms |
| コンパイル使用メモリ | 83,268 KB |
| 実行使用メモリ | 38,272 KB |
| 最終ジャッジ日時 | 2024-12-27 04:03:46 |
| 合計ジャッジ時間 | 165,718 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 30 RE * 8 TLE * 6 |
ソースコード
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
typedef long long LL;
const int M=1e7+10;
LL qmul(LL a,LL b,LL mod){
LL ans=0;
if(b<0){a=-a;b=-b;}
while(b>0)
{
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
LL qpow(LL a, LL b, LL mod){
if(b==0)return 1ll;
LL ans=1;
while(b>0){
if(b&1) ans=ans*a%mod;//ans=qmul(ans,a,mod);
a=a*a%mod;//a=qmul(a,a,mod);
b>>=1;
}
return ans;
}
LL gcd(LL a,LL b){
while(b){
LL t=a%b;
a=b;
b=t;
}
return b;
}
LL exgcd(LL a,LL b,LL &x,LL &y){
if(b == 0){
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a%b, x, y);
LL t = y;
y = x - y * (a / b);
x = t;
return d;
}
LL solveLinear(LL a,LL b,LL p){//ax=b mod p
a=(a%p+p)%p;b=(b%p+p)%p;
LL x,y;
LL d=exgcd(a,p,x,y);
//printf("d=%lld x=%lld y=%lld\n",d,x,y);
if(b%d!=0) return -1;
return ((b/d)*x%(p/d)+p/d)%(p/d);
//(qmul(b/d,x,p/d)+p/d)%(p/d);
}
LL invP(LL a,LL p){
a=(a%p+p)%p;
if(a==0) return -1;
LL x,y;
exgcd(a,p,x,y);
return (x%p+p)%p;
}
LL primeroot(LL P){
LL temp[1000],cnt;
LL x=P-1;
cnt=0;
for(LL i=2;i*i<=x;i++){
if(x%i==0){
while(x%i==0){
x/=i;
}
temp[cnt]=i;
cnt++;
}
}
if(x>1){
temp[cnt]=x;
cnt++;
}
for(LL g=2;g<=P-1;g++){
bool flag=1;
for(int i=0;i<cnt;i++){
if(qpow(g,(P-1)/temp[i],P)==1){
flag=false;
break;
}
}
if(flag){
return g;
}
}
return -1;
}
const LL hashmod=999983;
LL phash[hashmod+100];
LL r_origin[hashmod+100];
LL bsgs(LL a, LL b, LL p){//计算使得a^k=b modp的最小k
if(a % p == 0 && b % p == 0) return 1;
if(a % p == 0 && b % p != 0) return -1;
if(b % p == 1) return 0;
LL m = (LL)ceil(sqrt(p));
a = (a%p+p)%p;
LL r = (b%p+p)%p;
memset(phash,-1,sizeof(phash));
memset(r_origin,-1,sizeof(r_origin));
LL k;
phash[r%hashmod] = 0;//建立hash
r_origin[r%hashmod]=r;
for(LL j = 1; j < m; j++){//baby step
r=r*a%p;//r = qmul(r, a, p);
k=r%hashmod;
while(phash[k]!=-1) k++;
phash[k] = j;
r_origin[k]=r;
}
LL am = qpow(a, m ,p);//快速幂计算a^m
LL t = 1;
for(LL i = 1; i <= m; i++){//giant step
t=t*am%p;//t = qmul(t, am, p);
k=t%hashmod;
if(phash[k]!=-1){
while(phash[k]!=-1){
if(r_origin[k]==t) return m * i - phash[k];
k++;
}
}
}
return -1;
}
LL work(LL P,LL n,LL A){
LL g=primeroot(P);
//printf("g=%lld\n",g);
LL a=bsgs(g,A,P);
//printf("a=%lld\n",a);
LL x=solveLinear(n,a,P-1);
//printf("x=%lld\n",x);
if(x==-1) return -1;
return qpow(g,x,P);
}
int main(){
int T;
scanf("%d",&T);
for(;T>0;T--){
LL P,n,A;
scanf("%lld%lld%lld",&P,&n,&A);
LL X=work(P,n,A);
printf("%lld\n",X);
}
return 0;
}