Law of Commutation HDU - 6189(找规律+同余)

本文探讨了一道关于模指数运算的编程题,详细解析了如何根据输入参数的不同特性来寻找满足特定条件的整数个数。针对不同情况提出了有效的解决思路与算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Law of Commutation HDU - 6189

As we all know, operation ”+” complies with the commutative law. That is, if we arbitrarily select two integers a and b, a+b always equals to b+a. However, as for exponentiation, such law may be wrong. In this problem, let us consider a modular exponentiation. Give an integer m=2n and an integer a, count the number of integers b in the range of [1,m] which satisfy the equation ab≡ba (mod m
).

Input

There are no more than 2500 test cases.
Each test case contains two positive integers n and a seperated by one space in a line.

For all test cases, you can assume that n≤30,1≤a≤109
.

Output

For each test case, output an integer denoting the number of b
.
Sample Input

2 3
2 2

Sample Output

1
2

题意:给定n,a,其中令2n=m2n=m,现求区间[1,m]内有多少个b满足,ababbaba(mod m)。

解释:

1.当a为奇数的时候:
打表可以发现答案横为1,并且这个答案是a=b到时候
具体证明如下

对于a为奇数的情况,b一定为奇数,下证b=a mod 2^n。
由于奇数平方模8余1,故a^b=a mod 8, b^a=b mod 8
故a=b mod 8
由于奇数四次方模16余1,故a^b=a^(b%4) mod 16, b^a=b^(a%4) mod 16
由于b%4=a%4,故a=b mod 16
以此类推,得b=a mod 2^n。解唯一

2.当a为偶数的时候:
首先我们发现m=2nm=2n所以m是偶数,因为a是偶数所以abab是偶数,所以abab%m是偶数 baba % m是偶数,所以b是偶数。
令a= 2x, abab = (2x)b(2x)b = 2bxb2b⋅xb
此时我们又可以分出两种情况
一、b < n 的时候,因为题目给出到n很小,所以我们根据题意直接快速幂取模暴力算个数
二、b n 的时候,发现 2bxb2b⋅xb mod 2n2n恰好为0,所以我们只需要使babamod m为0即可,所以我们到目标转换成求满足babamod m为0的b的个数
设b=2xy2x⋅y,因为b是从[1,m]中找,所以我们只要找到b到最小值,用m除这个最小值就得到了,所有满足的b到个数,然后再减去[1,n]中到个数,因为已经求过了,所以就得到了b n情况下b到个数。
因为我们想要求最小到b,且b是偶数,所以我们就可以忽略倍数y到影响,直接考虑2x2x,要使得baba mod m = (2x)a(2x)a mod m = 2ax2ax mod 2n2n 0 mod 2n2n,只需要ax n,所以x nana,因此我们就找到了满足条件到最小x值使得b最小,因为要大于等于,所以求nana需要向上取整,即只要小数部分不为零,整数部分+1,小数部分变成0,求出b=2x2x,然后个数=mbnbmb−nb.
最后把总个数加起来
code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll q_pow(ll a,ll b,ll mod){
   ll ans = 1;
   while(b){
      if(b & 1)
        ans = ans * a % mod;
      b >>= 1;
      a = a * a % mod;
   }
   return ans;
}
ll n,a;
int main(){
   while(scanf("%lld%lld",&n,&a) != EOF){
       if(a & 1){
         printf("1\n");
         continue;
       }
       else{
         ll m = 1 << n;
         ll ans = 0;
         for(ll i = 1; i <= n; i++){
            if(q_pow(a,i,m) == q_pow(i,a,m))
               ans++;
         }
         ll b2 = n / a;
         if(b2 * a < n) b2++;
         ll b3 = 1 << b2;
         ll res = m / b3 - n / b3;
         ans = ans + res;
         printf("%lld\n",ans);
       }
   }
   return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值