【做题】UOJ450 - 复读机——单位根反演

原文链接 https://www.cnblogs.com/cly-none/p/UOJ450.html

题意:请自行阅读。

考虑用生成函数来表示答案。因为秒之间是有序的,所以这应当是个指数生成函数。故答案就是
\[ [x^n] \left( \sum_{i \geq 0} \frac {x^i} {i!} [d | i] \right)^k \]
突破口显然是在\([d|i]\)上。

于是考虑使用单位根反演。也就是
\[ \frac {1} {n} \sum_{i=0}^{n-1} \omega_{n}^{ik} = [n | k] \]
于是就直接带入,得到
\[ \begin{aligned} \sum_{i \geq 0} \frac {x^i} {i!} [d | i] = & \sum_{i \geq 0} \frac {x^i} {i!} \left (\frac 1 d \sum_{j=0}^{d-1} \omega_{d}^{ij} \right) \\ = & \frac 1 d \sum_{j=0}^{d-1} \sum_{i \geq 0} \frac {x^i \omega_{d}^{ij}} {i!} \\ = & \frac 1 d \sum_{j=0}^{d-1} e^{w_{d}^j x} \end{aligned} \]
本题中模数\(MOD\)\(19491001\),满足\(3 | (MOD -1)\)

考虑这道题中\(d \leq 3\),且我们很容易求出\(e^{kx}\)\(x^n\)前的系数。因此我们可以直接把这个式子展开为\(d\)项,再用二项式定理暴力计算答案。

复杂度是\(O(k^{d-1})\),能通过本题。(请注意所有四个子任务的分值之和为100)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
#define fir first
#define sec second
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define rrp(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define gc() getchar()
template <typename tp>
inline void read(tp& x) {
  x = 0; char tmp; bool key = 0;
  for (tmp = gc() ; !isdigit(tmp) ; tmp = gc())
    key = (tmp == '-');
  for ( ; isdigit(tmp) ; tmp = gc())
    x = (x << 3) + (x << 1) + (tmp ^ '0');
  if (key) x = -x;
}

const int N = 500010, MOD = 19491001, G = 7;
int jc[N], inv[N];
int power(int a,int b) {
  int ret = 1;
  while (b) {
    if (b & 1) ret = 1ll * ret * a % MOD;
    a = 1ll * a * a % MOD;
    b >>= 1;
  }
  return ret;
}
int comb(int a,int b) {
  if (a < b || a < 0 || b < 0) return 0;
  return 1ll * jc[a] * inv[b] % MOD * inv[a-b] % MOD;
}
int n,k,d,ans;
int main() {
  cin >> n >> k >> d;
  jc[0] = 1;
  rep (i, 1, k) jc[i] = 1ll * jc[i-1] * i % MOD;
  inv[k] = power(jc[k], MOD - 2);
  rrp (i, k-1, 0) inv[i] = 1ll * inv[i+1] * (i+1) % MOD;
  if (d == 1) {
    printf("%d\n", power(k, n));
  } else if (d == 2) {
    for (int i = 0 ; i <= k ; ++ i)
      (ans += 1ll * comb(k, i) * power(k - 2 * i, n) % MOD) %= MOD;
    ans = 1ll * ans * power((MOD + 1) / 2, k) % MOD;
    printf("%d\n", ans);
  } else if (d == 3) {
    int va = power(G, (MOD - 1) / 3);
    int vb = power(va, 2);
    int vc = power(va, 3);
    rep (a, 0, k) rep (b, 0, k-a) {
      int c = k - a - b;
      ans += 1ll * jc[k] * inv[a] % MOD * inv[b] % MOD * inv[c] % MOD * power((1ll * va * a + 1ll * vb * b + 1ll * vc * c) % MOD, n) % MOD;
      ans %= MOD;
    }
    ans = 1ll * ans * power(power(3, MOD-2), k) % MOD;
    printf("%d\n", ans);
  }
  return 0;
}


小结:无。

posted @ 2019-03-12 10:45 莫名其妙的aaa 阅读(...) 评论(...) 编辑 收藏