HDU-6189(Law of Commutation)

  1. 先打表可以发现当 a 为奇数的时候, 结果全为 1
  2. 当 a 为偶数时:
    因为a为偶数, 则a可以表示为 a = 2*k
    a^b%mod 可表示为: a^b%mod = 2^b * k^ b % 2 ^ n
    当b >= n 时, a^b%mod == 0 恒成立
           所以就要求满足此式: a^b%mod == b^a%mod == 0
           此时b肯定为偶数 则 b = 2*x
           要求成立: b^a%mod = 2^a * x^a % 2^n == 0
           所以分为两种情况:
           1. a > n 时: b^a%mod = 2^a * x^a % 2^n == 0 恒成立 结果为[1, mod]中的所有数-奇数情况-暴力情况
           2. a <= n 时: x一定要是一个2次幂数即 x = 2^p, (p*a) >= n 成立, 找到所有满足 p >= n/a 的数, 所以找到所有的数t, 满足 t >= x(x = 2^p) && t <= mod(mod = 2^n), 满足条件的数的数量为 mod/x - n/x
    当b < n 时, 暴力求解
#include <cmath>
#include <cstdio>
#include <iostream>

using namespace std;

typedef long long ll;
ll mod;

ll qpow(ll a, ll b) {
  ll res = 1;
  while (b) {
    if (b & 1)
      res = res * a % mod;
    b >>= 1;
    a = a * a % mod;
  }
  return res;
}

int main() {
  ll n, a;
  while (~scanf("%lld%lld", &n, &a)) {
    // a % 2 == 1; 结果恒为1
    mod = (1LL << n);
    if (a % 2 == 1) {
      printf("1\n");
      continue;
    } else {
      // b < n; 暴力求解
      ll res = 0;
      for (ll b = 1; b <= n; ++b) {
        ll t1 = qpow(a, b);
        ll t2 = qpow(b, a);
        if (t1 == t2) {
          res++;
        }
      }

      if (a > n) {
        res += mod / 2 - n / 2;
      } else {
        ll x;
        if (n % a != 0)
          x = n / a + 1;
        else
          x = n / a;

        x = (1LL << x);
        res += mod / x - n / x;
      }
      printf("%lld\n", res);
    }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37753409/article/details/81055884