题解 数论之神
这都什么神题啊
- 建议复习同余的基本性质
讲的很好的题解可惜有若干个地方是错的
发现模数不是质数,但模数肯定不含2这个质因子
所以将模数质因数分解之后每个 \(p_i^{c_i}\) 都是有原根的
于是尝试对每个 \(p_i^{c_i}\) 都做一遍然后crt合并
于是现在我们面临若干形如 \(x^a\equiv w \pmod{p^c}\) 的方程
注意这里的 \(w\) 可能与模数不互质,所以要分情况讨论
因为我太懒了所以见上面题解
注意第一种情况中应该设 \(x=p^t*k\),因为 \(x\) 可能有其它质因子,这也是解的数量是 \(p^{a-...}\) 而不是 \(a-...\) 的原因
然后关于为什么取值范围变了之后要乘上那个系数:注意取值范围其实是扩大到了原取值范围的整倍数
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int a, b;
ll ans, k;
unordered_map<ll, int> mp;
int p[N], c[N], sta[N], top, dcnt, g, phi, w, mod;
inline ll qpow(ll a, int b) {ll ans=1; for (; b; a=a*a%k,b>>=1) if (b&1) ans=ans*a%k; return ans;}
inline ll qpow(ll a, int b, ll mod) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
inline int gcd(int a, int b) {return !b?a:gcd(b, a%b);}
void divide(ll n) {
ll t=n; dcnt=0;
for (ll i=2; i*i<=n; ++i) if (t%i==0) {
p[++dcnt]=i; c[dcnt]=0;
do {t/=i; ++c[dcnt];} while (t%i==0);
}
if (t>1) p[++dcnt]=t, c[dcnt]=1;
// cout<<"p: "; for (int i=1; i<=dcnt; ++i) cout<<p[i]<<' '; cout<<endl;
}
int qphi(int n) {
int ans=n, t=n;
for (ll i=2; i*i<=n; ++i) if (t%i==0) {
ans=ans/i*(i-1);
do {t/=i;} while (t%i==0);
}
if (t>1) ans=ans/n*(n-1);
return ans;
}
bool isrt(int g, int p) {
for (int i=1; i<=top; ++i)
if (qpow(g, phi/sta[i], p)==1) return 0;
return 1;
}
int getrt(int p) { // p->p_i^{c_i}
// cout<<"getrt: "<<p<<' '<<phi<<endl;
int n=phi; top=0;
for (ll i=2; i*i<=phi; ++i) if (n%i==0) {
sta[++top]=i;
do {n/=i;} while (n%i==0);
}
if (n>1) sta[++top]=n;
// cout<<"sta: "; for (int i=1; i<=top; ++i) cout<<sta[i]<<' '; cout<<endl;
for (int i=1; ; ++i) {
// cout<<i<<' '<<p<<endl;
if (gcd(i, p)==1&&isrt(i, p))
return i;
}
}
int bsgs(int a, int b) {
mp.clear();
int m=ceil(sqrt(mod));
ll t=b, t2;
for (int j=0; j<=m; ++j) mp[t]=j, t=t*a%mod;
t=1, t2=qpow(a, m);
for (int i=1; i<=m; ++i) {
t=t*t2%mod;
if (mp.find(t)!=mp.end()) return i*m-mp[t];
}
return -1;
}
signed main()
{
int T=read();
while (T--) {
a=read(); b=read(); k=read()<<1|1;
divide(k); ans=1;
for (int i=1; i<=dcnt; ++i) {
mod=qpow(p[i], c[i], INF);
// cout<<"mod: "<<mod<<endl;
phi=(p[i]-1)*qpow(p[i], c[i]-1);
// cout<<"phi: "<<phi<<endl;
g=getrt(mod);
// cout<<"g: "<<g<<endl;
w=b%mod;
if (!w) ans*=qpow(p[i], c[i]-((c[i]-1)/a+1)); //, cout<<"ans: "<<qpow(p[i], c[i]-((c[i]-1)/a+1))<<endl;
else if (w%p[i]==0) {
int t=0, tw=w;
while (tw%p[i]==0) tw/=p[i], ++t;
if (t%a) ans=0;
else {
mod=qpow(p[i], c[i]-t);
int s=bsgs(qpow(g, a, mod), tw);
if (s==-1) ans=0;
else ans=ans*gcd(a, qphi(mod))*qpow(p[i], t-t/a);
}
}
else {
int s=bsgs(qpow(g, a, mod), w);
if (s==-1) ans=0;
else ans=ans*gcd(phi, a);
}
}
printf("%lld\n", ans);
}
return 0;
}