给定n,a, 在区间[1,2^n]求满足a^b %m =b^a %m的b的个数
直接用快速模幂从1遍历到2^n,会TL;
判断a为奇数时,答案为1,为偶数时b也偶数,遍历减去一半,还是会TL;还需要继续剪枝T…T
(1) a为奇数:
ans=1;
(2) a为偶数:
因为 m=2^n,m为偶数
所以 a^b %m 结果也为偶数
又因为 a^b %m = b^a % m
所以 b^a %m 结果也为偶数,b也为偶数
a为偶数
令a=2 * x => a^b=2^b * x^b
i, 当b<n时直接暴力
ii,当b>=n时,
(2^b * x^b) % 2^n =0 (因子取模为零)
此时b^a % 2^n 也要为零
b为偶数
令b=(2^x) * y => b^a=2^(ax) * y^a
即当 ax>=n时满足条件
x>=n/a,b=2^x * y;
对x限制后,只要满足x条件,无论y怎样,都可以取x=n/a,计算y个数即可
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
ll power(ll a,ll b){ //快速幂
ll result=1;
for(;b;b>>=1){
if(b&1){
result*=a;
}
a*=a;
}
return result;
}
ll quic_power(ll a,ll b,ll mod){ //快速模幂
ll result=1;
for(;b;b>>=1){
if(b&1){
result*=a;
result%=mod;
}
a*=a;
a%=mod;
}
return result;
}
int main(){
int n,a,cnt;
while(~scanf("%d%d",&n,&a)){
int ans=0;
if(a&1) //若a为奇数
ans=1;
else{
ll mod=power(2,n); //模 b [1,m]
cnt=0;
for(int i=2;i<=n;i+=2) //n以内满足条件的偶数b
if(quic_power(a,i,mod)==quic_power(i,a,mod))
cnt++;
ll x=n/a; //当b>n时
if(x*a<n)
x++;
ll b=power(2,x);
cnt+=(mod/b-n/b); //加上b>n之后满足条件的个数
ans=cnt;
}
printf("%d\n",ans);
}
return 0;
}