P2480 古代猪文 题解

题意:求

\[g^{\sum_{k\mid n}{n\choose k}} \]

\(999911659\) 取模。

\(1\le n,g\le 10^9\)

思路:

首先根据欧拉定理,题目转化为求 \(\displaystyle\sum_{k\mid n}{n\choose k}\)\(999911658\) 取模的值。

模数为合数不是很好做,因式分解发现 \(999911658=2\times 3\times 4679\times35617\),考虑中国剩余定理,分别求出 \(\displaystyle\sum_{k\mid n}{n\choose k}\)\(2,3,4679,35617\) 的值,用中国剩余定理合并即可。

由于 \(n\) 的因数个数是 \(\mathcal{O}(\sqrt{n})\) 的,直接暴力枚举 \(k\) 然后卢卡斯定理算组合数即可。

一道挺好的综合练习题。

#include <iostream>

using namespace std;

const int kM = 999911659;
const int kL[4] = {2, 3, 4679, 35617};

int n, g;

int P(int b, int e, int p) {
  int s = 1;
  for (; e; e >>= 1, b = 1LL * b * b % p) {
    (e & 1) && (s = 1LL * s * b % p);
  }
  return s;
}
struct Solver {
  static const int kP = 3.6e4 + 1;

  int p, vf[kP], ivf[kP];
  Solver(int p) : p(p) {
    vf[0] = 1;
    for (int i = 1; i < p; ++i) {
      vf[i] = 1LL * vf[i - 1] * i % p;
    }
    ivf[p - 1] = P(vf[p - 1], p - 2, p);
    for (int i = p - 1; i >= 1; --i) {
      ivf[i - 1] = 1LL * ivf[i] * i % p;
    }
  }
  int C(int n, int m) {
    if (n < p && m < p) {
      return n >= m ? 1LL * vf[n] * ivf[m] % p * ivf[n - m] % p : 0;
    }
    return 1LL * C(n / p, m / p) * C(n % p, m % p) % p;
  }
  int operator()() {
    int ans = 0;
    for (int k = 1; k * k <= n; ++k) {
      if (n % k == 0) {
        ans = (ans + C(n, k)) % p;
        if (k != n / k) {
          ans = (ans + C(n, n / k)) % p;
        }
      }
    }
    return ans;
  }
};

int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  cin >> n >> g;
  g %= kM;
  if (!g) {
    cout << '0';
    return 0;
  }
  int s = 0;
  for (int i = 0; i < 4; ++i) {
    int vm = (kM - 1) / kL[i];
    int im = P(vm, kL[i] - 2, kL[i]);
    s = (s + 1LL * Solver(kL[i])() * vm % (kM - 1) * im % (kM - 1)) % (kM - 1);
  }
  cout << P(g, s, kM);
  return 0;
}
posted @ 2023-05-25 20:23  bykem  阅读(13)  评论(0编辑  收藏  举报