【NOIP模拟】 (10.24) T3 math

math

题目描述:
    给定两个数字a和n,求有多少数字b满足a^b mod 2^n = b^a mod 2^n,且1<=b<=2^n

输入格式:
    第一行一个整数T代表数据组数。
    接下里T行,每行两个数a和n。

输出格式:
    对于每组数据输出一个整数表示b的个数

数据范围:
    对于30%的数据:n<=20;T<=10
    对于100%的数据:1<=n<=30;1<=a<=10^9;T<=1000。

解析:
    对于30%的数据,快速幂枚举。
    对于100%的数据,我们有两种方法,一种是数学证明,一种是打表找规律。

    我们来数学证明一下:
    当a为奇数时,b一定为奇数,证:b mod 2^n = a mod 2^n

    已知奇数的平方模8余1,我们可以设b=2k+1;
    则a^b mod 8 = a^(2k+1) mod 8 =(a^2k * a) mod 8 = ((a^k)^2 mod 8) * (a mod 8)
    因为a^k一定为奇数,所以((a^k)^2 mod 8) * (a mod 8) = 1 * a mod 8  = a mod 8
    同理证得b^a mod 8 = b mod 8,所以b mod 2^3 = a mod 2^3

    已知奇数的四次方模16余1,我们可以分别设
    当b=4k+1时
    则a^b mod 16 =a^(4k+1) mod 16 =(a^4k * a) mod 16 = ((a^k)^4 mod 16) * (a mod 16)
    因为a^k一定为奇数,所以((a^k)^4 mod 16) * (a mod 16) = 1 * a mod 16 = a mod 16
   b=4k+3时
    同理得a^b mod 16 = a^3 mod 16 = (a^2 * a) mod 16 =a mod 16
    同理证得b^a mod 16 = b mod 16,所以b mod 2^4 = a mod 2^4

    以此类推,得b mod 2^n = a mod 2^n。又因为1<=b<=2^n,所以b要使条件满足b只有一个解

    当a为偶数时,b一定为偶数
    当a>=n时,显然b^a mod 2^n = 0 mod 2^n = 0
    设b = 2^(n/a),则b^a = (2^(n/a))^a = 2^n,要使得b^a mod 2^n = 0,则n/a应该向上取整。因为n/a如果不能整除,那么2^(n/a)^a将会比2^n小,不能整除。
    当a<n时,因为a<=30,所以可以直接用快速幂暴力枚举

时间复杂度 O(nloga)

代码:
#include <bits/stdc++.h>
using namespace std;

int t;
int a,n;
int ans,mod;

inline int ksm(long long a,long long b,long long c)  //快速幂
{
   int ans=1;
   a=a%c;
   while(b)
   {
   	 if(b&1) ans=(ans*a)%c;
   	 b=b>>1;
   	 a=(a*a)%c;
   }
   return ans;
}

int main()
{
  // freopen("math.in","r",stdin);
   //freopen("mat.out","w",stdout);

   scanf("%d",&t);
   while(t--)
   {
   	 scanf("%d%d",&a,&n);
   	 if(a&1) cout<<"1"<<endl;
   	 else
   	 {
   	   ans=0;
	   int x=0;
	   x+=ceil((double)n/a);          //ceil函数:向上取整。注意要先转为double类型
   	   mod=1<<n;
   	   ans=mod/(1<<x)-n/(1<<x);
   	   for(int i=1;i<=n;i++)           //这里i要取到1的原因是ceil函数是算出大于该数的最小整数
   	     if(ksm(a,i,mod)==ksm(i,a,mod)) ans++;
   	   cout<<ans<<endl;
   	 }
   }

   return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值