NOIP模拟 Math - 数学

题目大意:

给定a,n(\(a \le 1e9, n\le30\)),求有多少\(b(1 \le b \le 2^n)\)满足:\(a^b \equiv b^a(mod 2^n)\)

题目分析:

数学被吊打。
打表发现a为奇数时,b只有1种。
a为偶数时,b一定为偶数。
对于\(b < n\)的部分,直接暴力快速幂(不要脑抽加快速乘)。
对于\(b \ge n\)的部分,\(a^b \equiv 0 (mod 2^n)\),\(b^a \equiv 0 (mod 2^n)\),设\(b=2^x·y\),那么\(b^a = 2^{ax}·y^a\),如果\(2^{ax} \ge 2^n\)\(ax \ge n\),即\(x \ge \left \lceil \frac{n}{a} \right \rceil\),也就是b是\(2^{\left \lceil \frac{n}{a} \right \rceil}\)的倍数。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 35;
int a, n, T;

inline int ksm(int x, int y, int mod){
	int ret = 1;
	for(; y; y >>= 1, x = (1ll*x*x) % mod)
		if(y & 1) ret = (1ll*ret*x) % mod;
	return ret;
}

int main(){
	scanf("%d", &T);
	while(T--){
		scanf("%d%d", &a, &n);
		if(a & 1){
			printf("1\n");
			continue;
		}
		else{
			int ans = 0;
			for(int i = 2; i <= n; i+=2){
				if(ksm(a, i, (1<<n)) == ksm(i, a, (1<<n))) 
					ans++;
			}
			int delta = n/a + (n % a ? 1 : 0);
			ans += (1<<n)>>delta;   //有多少个倍数 
			ans -= (n>>delta);      //减少重复算的
			printf("%d\n", ans); 
		}
	}
	return 0;
}
posted @ 2017-10-24 19:01  CzYoL  阅读(178)  评论(0编辑  收藏  举报