zoukankan      html  css  js  c++  java
  • BZOJ4555 求和

    题面

    解:把第二类斯特林数和组合数拆开。

    惊讶的发现推不下去了......后面那个i的∑跟j有关,不能卷积。

    这时发现一开始的式子,j的上界可以改为n。

    于是这里i的下界改为1。就是一个常数,可以卷积。

    卷积出来之后枚举j即可。

      1 #include <bits/stdc++.h>
      2 
      3 typedef long long LL;
      4 
      5 const int N = 100010, MO = 998244353;
      6 
      7 int A[N << 2], B[N << 2], r[N << 2];
      8 int fac[N], inv[N], invn[N];
      9 
     10 inline int qpow(int a, int b) {
     11     int ans = 1;
     12     while(b) {
     13         if(b & 1) ans = 1ll * ans * a % MO;
     14         a = 1ll * a * a % MO;
     15         b = b >> 1;
     16     }
     17     return ans;
     18 }
     19 
     20 inline void prework(int n) {
     21     static int R = 0;
     22     if(R == n) return;
     23     R = n;
     24     int lm = 1;
     25     while((1 << lm) < n) lm++;
     26     for(int i = 1; i < n; i++) {
     27         r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1));
     28     }
     29     return;
     30 }
     31 
     32 inline void NTT(int *a, int n, int f) {
     33     prework(n);
     34     for(int i = 0; i < n; i++) {
     35         if(i < r[i]) std::swap(a[i], a[r[i]]);
     36     }
     37     for(int len = 1; len < n; len <<= 1) {
     38         int Wn = qpow(3, (MO - 1) / (len << 1));
     39         if(f == -1) Wn = qpow(Wn, MO - 2);
     40         for(int i = 0; i < n; i += (len << 1)) {
     41             int w = 1;
     42             for(int j = 0; j < len; j++) {
     43                 int t = 1ll * a[i + len + j] * w % MO;
     44                 a[i + len + j] = (a[i + j] - t) % MO;
     45                 a[i + j] = (a[i + j] + t) % MO;
     46                 w = 1ll * w * Wn % MO;
     47             }
     48         }
     49     }
     50     if(f == -1) {
     51         int inv = qpow(n, MO - 2);
     52         for(int i = 0; i < n; i++) {
     53             a[i] = 1ll * a[i] * inv % MO;
     54         }
     55     }
     56     return;
     57 }
     58 
     59 inline int C(int n, int m) {
     60     if(n < 0 || m < 0 || n < m) return 0;
     61     return 1ll * fac[n] * invn[m] % MO * invn[n - m] % MO;
     62 }
     63 
     64 inline int getQ(int a, int q, int n) {
     65     if(q == 1) {
     66         return 1ll * a * n % MO;
     67     }
     68     else {
     69         return 1ll * a * (qpow(q, n) - 1) % MO * qpow(q - 1, MO - 2) % MO;
     70     }
     71 }
     72 
     73 int main() {
     74     int n;
     75     scanf("%d", &n);
     76     fac[0] = inv[0] = invn[0] = 1;
     77     fac[1] = inv[1] = invn[1] = 1;
     78     for(int i = 2; i <= n; i++) {
     79         fac[i] = 1ll * fac[i - 1] * i % MO;
     80         inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO;
     81         invn[i] = 1ll * invn[i - 1] * inv[i] % MO;
     82     }
     83 
     84     /// solve
     85     for(int i = 0; i <= n; i++) {
     86         A[i] = invn[i] * ((i & 1) ? -1 : 1);
     87         B[i] = 1ll * invn[i] * getQ(1, i, n + 1) % MO;
     88     }
     89     int len = 1;
     90     while(len <= n * 2) len <<= 1;
     91     NTT(A, len, 1); NTT(B, len, 1);
     92     for(int i = 0; i < len; i++) {
     93         A[i] = 1ll * A[i] * B[i] % MO;
     94     }
     95     NTT(A, len, -1);
     96 
     97     int ans = 0;
     98     for(int i = 0; i <= n; i++) {
     99         ans = (ans + 1ll * fac[i] * qpow(2, i) % MO * A[i] % MO) % MO;
    100     }
    101     printf("%d
    ", (ans + MO) % MO);
    102     return 0;
    103 }
    AC代码

     解法二:资料1资料2

  • 相关阅读:
    BT5启动SSH服务
    RIP路由协议的水平分割和触发更新
    FATFS Copy Files
    spi master vhd
    altera cpld spi master verilog
    SPI bus master for System09
    How To Set a Status Flag in One Clock Domain, Clear It in Another
    VHDL 整数 小数 分数 分频
    vhdl 状态机
    The DualModulus Divider in VHDL
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10886941.html
Copyright © 2011-2022 走看看