LOJ #562. 「LibreOJ Round #9」Tangjz 的背包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wxh010910/article/details/80736601

链接:

link

题解:

P=998244353,r=19190506,q=1r ,那么答案就是 rpm[xm]i=0n1(1+qix)

根据 wiki ,有 [xm]i=0n1(1+qix)=qm(m1)2(nm)q

定义 [k]q=i=0k1qi=qk1q1[n]q!=i=1n[i]q ,那么 (nm)q=[n]q![m]q![nm]q!

注意到 q1 在分子分母中出现的总次数都相等,那么可以忽视掉。

aqP 的阶, F(n)=i=1n(qi1) ,将 F(n) 分成两部分,模 P0 的和不为 0 分别计算,有:

F(n)=(i=1na(qai1))(i=1,ain(qi1))

对于后面部分是很好计算的,考虑算前面部分:

qai1=(qa1)(j=0i1qaj)

注意到后面那个玩意就是 i ,所以前面部分就是 na!(qa1)na

如果 nama+nma ,那么答案显然是 0 ,否则消掉 0 之后就是 (nama)

这里 a 大约是 106 ,所以 ana 都不是很大,暴力预处理一些东西就可以了。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1100000;
const int q = 768906335;
const int r = 19190506;
const int mod = 998244353;
const int period = 917504;

int f[N], g[N], fac[N], ifac[N];

int add(int x, int y) {
  x += y;
  if (x >= mod) {
    x -= mod;
  }
  return x;
}

int mul(int x, int y) {
  return (ll)x * y % mod;
}

int power(int x, int y) {
  int result = 1;
  while (y) {
    if (y & 1) {
      result = mul(result, x);
    }
    x = mul(x, x);
    y >>= 1;
  }
  return result;
}

int binom(int n, int m) {
  return mul(fac[n], mul(ifac[m], ifac[n - m]));
}

int fact(int n, int m) {
  return mul(f[n], mul(g[m], g[n - m]));
}

int main() {
#ifdef wxh010910
  freopen("input.txt", "r", stdin);
#endif
  f[0] = g[0] = 1;
  for (int i = 1, coef = 1; i < period; ++i) {
    coef = mul(coef, q);
    f[i] = mul(f[i - 1], coef - 1);
    g[i] = mul(g[i - 1], power(coef - 1, mod - 2));
  }
  fac[0] = ifac[0] = fac[1] = ifac[1] = 1;
  int limit = (1000000000000ll + period - 1) / period;
  for (int i = 2; i <= limit; ++i) {
    fac[i] = mul(fac[i - 1], i);
    ifac[i] = mul(mod - mod / i, ifac[mod % i]);
  }
  for (int i = 2; i <= limit; ++i) {
    ifac[i] = mul(ifac[i - 1], ifac[i]);
  }
  int T;
  scanf("%d", &T);
  while (T--) {
    ll n, m;
    scanf("%lld %lld", &n, &m);
    if (n / period != m / period + (n - m) / period) {
      puts("0");
      continue;
    }
    int p = ((n - m) % period) * (m % period) % period;
    int answer = power(r, p);
    answer = mul(answer, binom(n / period, m / period));
    answer = mul(answer, fact(n % period, m % period));
    printf("%d\n", answer);
  }
  return 0;
}

没有更多推荐了,返回首页