【题解】P6730 [WC2020] 猜数游戏
本题的前置是弱化版的 P5605 小 A 与两位神仙
要求所有询问集合大小之和,考虑拆贡献,变成每个数出现在多少个子集的询问集合中。
先刻画什么时候一个数 \(a\) 会被放进询问集合,容易观察到的一点是,不存在另一个 \(b\) 使得 \(b\) 的某个幂次与 \(a\) 同余。(此时先询问 \(b\) 以后 \(a\) 会被报出来,包括 \(a\) 的幂次也会被报出来),而且若不存在这样的 \(b\) ,则 \(a\) 一定需要询问自己本身,故该条件是充要的。
推导一下 \(\exist m,\ s.t.\ b^m\equiv a\pmod p\) 的等价形式,这其实是 P5605 的内容,放在这里再写一下。
显然 \(a,b\) 要么都与 \(p\) 互质,要么都不与 \(p\) 互质
先考虑 \(a,b\) 均与 \(p\) 互质的情况
因为 \(p\) 是素数或奇素数幂,则由原根存在定理知 \(p\) 存在原根 \(g\) 。
设 \(b=g^y,a=g^x\) ,有 \(g^{ym}\equiv g^x\pmod p\) ,故 \(ym\equiv x\pmod {\varphi(p)}\)
这个式子可以看成二元一次不定方程,\(m\) 有解 \(\iff\) \(\gcd(y,\varphi(p))|x\)
由于 \(\gcd(y,\varphi(p))|\varphi(p)\) ,故上式等价于 \(\gcd(y,\varphi(p))|\gcd(x,\varphi(p))\)
因为 \(\delta_p(g^y)=\displaystyle\frac{\delta_p(g)}{\gcd(\delta_p(g),y)}\),而 \(\delta_p(g)=\varphi(p)\)
故 \(\gcd(y,\varphi(p))=\gcd(\delta_p(g),y)=\displaystyle\frac{\delta_p(g)}{\delta_p(g^y)}\)
因此只需 \(\displaystyle\frac{\delta_p(g)}{\delta_p(g^y)}\mid\frac{\delta_p(g)}{\delta_p(g^x)}\), 即 \(\delta_p(a)\mid\delta_p(b)\),求出每个数的阶只需对 \(\varphi(p)\) 的因数判断即可
再考虑 \(a,b\) 均不与 \(p\) 互质的情况
设 \(p\) 的质因子为 \(q\) (\(q\) 可以为 \(p\) 本身),则 \(q\mid a\),\(q\mid b\)
则 \(b\) 的若干幂次以后必为 \(p\) 的倍数,只需暴力枚举 \(m\) ,时间复杂度 \(O(\log p)\)
到这里基本上已经结束了,只需要将所有数按照是否与 \(p\) 互质分成两大类,两类中对每个数 \(x\) 分别统计有多少数可以经过乘幂到达自己,记为 \(cnt_x\)。因此若 \(x\) 在询问集合中,则原集合中必没有这 \(cnt_x\) 个数,剩下的数在不在原集合无所谓,贡献为 \(2^{cnt_x}\)。但注意到 阶相等的多个数之间形成强连通分量,对它们钦定一个顺序即可。另一种解决方法是对所有阶进行枚举,每个阶中至少出现一个数,故再乘上 \(2^k-1\) 即可,其中 \(k\) 为 阶是当前枚举值的数的个数。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=5009;
const ll MOD=998244353;
ll n,p,q,phi,nD,d[N],pw2[N];
ll cnt[N],ans;
vector<ll> vec;
map<ll,ll> mp,id;
inline ll qpow(ll a,ll b,ll MOD){
ll res=1;
while(b){
if(b&1) res=(res*a)%MOD;
a=(a*a)%MOD;
b>>=1;
}
return res;
}
inline ll get(ll x){
ll res=phi;
for(ll i=1;i<=nD;i++){
while(res%d[i]==0&&qpow(x,res/d[i],p)==1){
res/=d[i];
}
}
return res;
}
void init(){
pw2[0]=1;
for(ll i=1;i<=n;i++) pw2[i]=pw2[i-1]*2%MOD;
for(ll i=2;i*i<=p;i++){
if(p%i==0){
q=i;
break;
}
}
if(q==0) q=p;
phi=p-p/q;
ll x=phi;
for(ll i=2;i*i<=x;i++){
if(x%i==0){
d[++nD]=i;
while(x%i==0){
x/=i;
}
}
}
if(x>1) d[++nD]=x;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>p;
init();
for(ll i=1;i<=n;i++){
ll a; cin>>a;
if(a%q==0){
id[a]=vec.size();
vec.push_back(a);
}
else{
ll ord=get(a);
mp[ord]++;
}
}
fill(cnt,cnt+vec.size(),n);
for(ll i=0;i<vec.size();i++){
ll u=vec[i];
for(ll v=u;v;v=v*u%p){
if(id.count(v)){
cnt[id[v]]--;
}
}
}
for(ll i=0;i<vec.size();i++){
ans+=pw2[cnt[i]];
}
for(auto u:mp){
ll res=n;
for(auto v:mp){
if(v.first%u.first==0){
res-=v.second;
}
}
ans+=pw2[res]*(pw2[u.second]-1)%MOD;
}
printf("%lld\n",ans%MOD);
return 0;
}

浙公网安备 33010602011771号