1. 程式人生 > 其它 >P6610 - 同餘方程 題解

P6610 - 同餘方程 題解

一道卓越得讓我五體投地的好題/ww


首先拆 CRT 是顯然的吧()。將 \(p\) 拆成若干個奇質數 \(p_i\) 的乘積,設 \(a^2+b^2\equiv x\pmod{p_i}\) 的解集 \(X_i\)(是個二元組集合喲),則從每個 \(X_i\) 中選一組出來都能用 CRT 合併成一個模 \(p\) 的解,所以答案就是 \(\prod|X_i|\)(不需要寫 CRT 喲)。

下面考慮 \(p\) 是奇質數怎麼做。容易想到換元,令 \(y=a^2,z=b^2\),設 \(f(A)=[A\text{ 是模 }p\text{ 二次剩餘噠!}]\),則答案就是 \(4\sum\limits_{y\not\equiv 0,y\not\equiv x}f(y)f(x-y)\)

,再加上 \(0\)\(x\) 的貢獻。後者是 trivial 的,考慮前者怎麼求。

由於列舉條件是 \(y\not\equiv0,y\not\equiv x\),本能地分 \(x\) 是否為 \(0\) 討論。如果等於那是比較簡單的,設 \(m=\dfrac{p-1}2\),任取原根 \(g\),設 \(y\equiv g^\alpha\),則顯然 \(-y\equiv -g^\alpha\equiv g^{m+\alpha}\)。如果 \(m\) 是偶數,那麼 \(f(y)=f(-y)\),於是 sum 列舉的有一半都是 \(1\),算出來就是 \(4\times\dfrac{p-1}2=2(p-1)\)

\(m\) 是奇數的話有 \(f(y)=-f(-y)\),這兩者永遠不可能同時為 \(1\),那就寄了,算出來是 \(0\)

\(x\not\equiv0\) 乍一看感覺很離譜,覺得不可做,因為加法和二次剩餘放一塊就像世紀難題(霧水)。但注意到二次剩餘判定方法,\(f(A)=[A^{m}\equiv 1]\),這樣 \(f(A)=0\) 對應 \(A^m\equiv-1\)\(f(A)=1\) 對應 \(A^m\equiv 1\),於是有 \(f(A)=\dfrac{A^m\bmod p+1}2\)!這樣就把一個真值表達式變成了代數式!但一個問題是,要求的 \(\sum\) 是在 \(\Z\)

上的,而這樣表示 \(f(A)\) 是在 \(\Z_p\) 上的,這就意味著如果按照這個表示式計算 \(\sum\),只能得到模 \(p\) 意義下的值。接下來是最神仙的地方:只需要知道模意義下的值,便可知道真實值,因為 \(\sum f(y)f(x-y)\in[0,p-2]\)!!!!

接下來就略顯 trivial 了。忽略 \(f(A)\) 的分母,最後乘個 \(4\) 的逆元即可。顯然

\[\sum (y^m+1)((x-y)^m+1)=\sum(y^m(x-y)^m+y^m+(x-y)^m+1) \]

第四項的和顯然是 \(p-2\)。第二三項是對稱的,分別能取遍 \([1,p)\backslash \{x\}\),而 \([1,p)\)\(m\) 次方一半是 \(1\) 一半是 \(-1\),總和就是 \(0\),所以取 \(-x^m\) 就行了。第一項的話,乘進去得到 \(\!\left(xy-y^2\right)^m\),除以 \(y^2\) 顯然值不變,為 \(\left(\dfrac xy-1\right)^m\)。這就比較簡單,\(\dfrac xy\) 顯然取遍 \([2,p)\),於是 \(\dfrac xy-1\) 取遍 \([1,p-2]\)

code
int solve(int p, int x) {
	if(x == 0) return (p - 1) % 4 == 0 ? 2 * p - 1 : 1;
	int m = p - 1 >> 1;
	int ans = p - 2;
	(ans += 2 * -qpow(x, m, p)) %= p;
	(ans += -qpow(p - 1, m, p)) %= p;
	ans = (ans + 10 * p) * inv(4, p) % p * 4;
	return ans + 4 * (qpow(x, m, p) == 1);
}

void mian() {
	int p = read(), x = read();
	int ans = 1;
	for(int i = 2; i * i <= p; ++i) if(p % i == 0) {
		ans *= solve(i, x % i);
		p /= i;
	} if(p > 1) ans *= solve(p, x % p);
	prt(ans), pc('\n');
}