at_abc335_g 题解
Solution
标题上面说了这是离散对数问题。于是我们不妨找出原根,然后用 BSGS 求出每个数的离散对数。这样等价于
但是很遗憾,BSGS 是复杂度是错的。于是我们考虑求出每个数对
然后考虑怎么求阶。我们枚举
这样你最多进行
好它过了。
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=2e5+10;
int n,p,a[MAXN];
int qpow(__int128 base,int p,int mod) {
__int128 ans=1;
while(p) {
if(p&1) ans=ans*base%mod;
base=base*base%mod,p>>=1;
}
return ans;
}
vector<int> frac;
map<int,int> mp;
int calc_b(int v) {
int ans=p-1;
for(auto id:frac) if(qpow(v,ans/id,p)==1) ans/=id;
return (p-1)/ans;
}
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>p; ffor(i,1,n) cin>>a[i];
int v=p-1;
ffor(i,2,v/i) while(v%i==0) frac.push_back(i),v/=i;
if(v) frac.push_back(v);
sort(frac.begin(),frac.end());
ffor(i,1,n) mp[calc_b(a[i])]++;
int ans=0;
for(auto pr1:mp) for(auto pr2:mp) if(pr1.first%pr2.first==0) ans+=pr1.second*pr2.second;
cout<<ans;
return 0;
}