BSGS 算法与 8.27 T1
BSGS 算法与 8.27 T1
Problem
给你三个整数 \(a,b,p\) 求最小的 \(x\in\N\) 使得 \(a^x\equiv b \pmod{p}\) 且 \(a\perp p\) 。
Solution
要解决这个问题就要请出 \(BSGS\) 算法了,原理如下。
设 \(x=A\lceil\sqrt{p}\rceil-B\) 其中 \(0\le A,B\le \lceil\sqrt{p}\rceil\),则有 \(\large a^{A\lceil\sqrt{p}\rceil-B}\equiv b \pmod{p}\) 。
把指数上的 \(B\) 甩过去可得 \(\large a^{A\lceil\sqrt{p}\rceil}\equiv ba^B \pmod{p}\)。
考虑枚举所有的 \(B\) ,算得每一个 \(ba^B\) ,把所有的 \(ba^B\) 甩进 \(hash\) 表里头,在枚举 \(A\) 看是否能凑出来 \(\large a^{A\lceil\sqrt{p}\rceil} \bmod p= ba^B\) 。
例题:8.27 测试 T1
Description
给你一个数 \(p\),缩剩余系是指由 \([1,p]\) 之间的与 \(p\) 互质的整数组成的集合。现在给你一个数 \(a\),求在模 \(p\) 意义下 \(a\) 的幂集有多少个不同的值。(形如 \(1, a, a^2, a^3, \ldots\) 的数叫做 \(a\) 的幂集 ) 其中 \(p\perp a\)。
\(1 < p \leq 10^8\),\(T \leq 500\)
注意到在模 \(p\) 意义下 \(a\) 的幂集是会循环的,而题目中所求有多少个不同的值正是循环节的长度。
而又注意到 \(a^0 \equiv 1\pmod{p}\) 则问题变为求最小的 \(x\in\N_+\) 使得 \(a^x\equiv 1 \pmod{p}\) 且 \(a\perp p\)。
则可用 \(BSGS\) 算法解决。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int ksm(int a,int b,int p){
if(b==0) return 1;
if(b==1) return a%p;
int fk=ksm(a,b/2,p);
if(b%2==0) return fk*fk%p;
else return (((fk*fk)%p)*a)%p;
}
int fq(int a,int b,int p){
map<int,int> hash;
hash.clear();
b%=p;
int t=(int) sqrt(p) +1;
for(int j=0;j<t;j++){
int val=b*ksm(a,j,p)%p;
hash[val]=j;
}
a=ksm(a,t,p)%p;
if(a==0) return b==0 ? 1:-1;
for(int i=1;i<=t;i++){//这里要从 1 开始,因为要求的 x 为正整数
int val=ksm(a,i,p);
int j=hash.find(val)==hash.end() ? -1:hash[val];
if(j>=0 && i*t-j>=0) return i*t-j;
}
return -1;
}
signed main(){
// freopen("1th.in","r",stdin);
// freopen("1th.out","w",stdout);
int t;
cin>>t;
while(t--){
int p,a;
cin>>p>>a;
cout<<fq(a,1,p)<<endl;
}
}

浙公网安备 33010602011771号