【2】做题心得 - 杂题 - 数学题

说白了,就是 \(n\leq 30\),\(a\leq 10^9\) 求 \(a^b\equiv b^a(\bmod 2^n)\)。

我们发现这坨东西不好处理,所以我们考虑看 \(a\) 的奇偶性。为什么这样考虑呢?因为 \(a\bmod 2=1\) 的时候有显然的答案。

\(a\) 为奇数的情况

首先我们发现此时 \((a^b,2^n)=1\) 且 \((b^a,2^n)=1\)。因为 \(a\) 为奇数,然后我们发现 \(a^b\equiv b^a\)。我们想要让 \(a^b\bmod 2^n = b^a \bmod 2^n\) 那么我们可以让 \(a^b=b^a\),此时显然 \(b\) 唯一解。然后我们为了让 \(a^b\equiv b^a\),此时 \(|a^b-b^a|\ge 2^n\),我们发现这是不可能同余的(\(a\neq b\))所以综上 \(a\bmod 2=1\) 时,仅存在一组 \(a=b\) 的解。

\(a\) 为偶数的情况

我们发现这时 \(a^b \bmod 2^n\) 可以为 \(0\) 仅当 \(2^\frac{ab}{2}\ge 2^n\)。所以当 \(b\leq n\) 的时候可以考虑暴力枚举(\(n\leq 30\))否则我们发现我们需要 \(b^a|2^n\)。显然的,\(b\) 需要满足 \(b=k2^x\),不然无法出现同余。所以,\(b^a=k^a2^{ax}\)。同时因为 \(2^{ax}\ge2^n\),所以 \(ax\ge n\),$x\ge \lceil \frac{n}{a} \rceil $。由此可以推出 \(b^a=k^a2^{ax- \lceil \frac{n}{a} \rceil}2^{ \lceil \frac{n}{a} \rceil}\) 。这看起来很复杂,但是我们知道了 \(n< k^a2^{ax- \lceil \frac{n}{a} \rceil}2^{ \lceil \frac{n}{a} \rceil}\leq 2^n\)。我们就发现 \(\frac{n}{2^{ \lceil \frac{n}{a} \rceil}}<k^a2^{ax- \lceil \frac{n}{a} \rceil}\le \frac{2^n}{2^{ \lceil \frac{n}{a} \rceil}}\)。这里的 \(k^a2^{ax- \lceil \frac{n}{a} \rceil}\) 没有了约束,那么这个东西的整数解数量就是答案。

具体的,我们设 \(y=\lceil \frac{n}{a} \rceil\),并预处理出 \(n\leq 50\) 时 \(2^n\) 的值 \(mul_n\)(防止越界)然后我们直接计算 \(mul_{n-y}-\lfloor \frac{n}{mul_y}\rfloor\),输出即可。

最终总结

这道题我们通过分类 \(a\) 的值,归纳出了 \(b\) 的取值范围,求出了 \(a^b\equiv b^a(\bmod 2^n)\) 的答案。当然要是你觉得过于复杂,可以考虑通过其他的方法直接求出 \(b\ge n\) 的范围。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a,n,ans,mul[55];
int qp(int a,int b,int p){
	int res=1;
	while(b){
		if(b&1)
			res=(res*a)%p;
		a=(a*a)%p,b>>=1;
	}
	return res;
}
signed main(){
	mul[0]=1;
	for(int i=1;i<=50;i++)
		mul[i]=mul[i-1]*2;
	int T;
	cin>>T;
	while(T--){
		cin>>a>>n;
		if(a&1)
			cout<<1<<"\n";
		else{
			ans=0;
			for(int b=1;b<=n;b++)
				if(qp(a,b,mul[n])==qp(b,a,mul[n]))
					++ans;
			int y=n/a+bool(n%a);
			ans+=mul[n-y]-n/mul[y];
			cout<<ans<<"\n";
		}
	}	
	return 0;
}

https://www.luogu.com.cn/article/9bn98yo2

posted @ 2026-10-12 11:52  Ivan422  阅读(3)  评论(0)    收藏  举报