题解 数论之神

传送门

这都什么神题啊

讲的很好的题解可惜有若干个地方是错的
发现模数不是质数,但模数肯定不含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;
}
posted @ 2022-01-01 14:52  Administrator-09  阅读(2)  评论(0编辑  收藏  举报