• LOJ泛做


    SDOI2019 快速查询

    考虑维护双标记,题目的难点在于如何维护单点赋值操作。

    推式子发现,直接修改原本的值变为$frac{x-add}{mul}$,用hash维护下标即可。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define MOD 10000019
      4 namespace hash{
      5     #define sz 299999
      6     int h[300010], num[300010], clo[300010];
      7     int All, CLO;
      8     inline int get_Num(int x) {
      9         int wt = x % sz;
     10         while(num[wt] != x && num[wt]) {
     11             ++ wt;
     12             if(wt == sz) wt = 0;
     13         }
     14         num[wt] = x;
     15         return wt;
     16     }
     17     inline int upd(int x, int y, int CL) {
     18         int wt = get_Num(x);
     19         if(clo[wt] < CLO) h[wt] = All;
     20         int ret = y - h[wt];
     21         h[wt] = y; clo[wt] = CL;
     22         return ret;
     23     }
     24     inline int query(int x) {
     25         int wt = get_Num(x);
     26         if(clo[wt] < CLO) h[wt] = All, clo[wt] = CLO;
     27         return h[wt];
     28     }
     29 }
     30 int inv[MOD+10];
     31 inline void init() {
     32     inv[0] = inv[1] = 1;
     33     for(int i = 2; i < MOD; ++ i) {
     34         inv[i] = 1ll * inv[MOD % i] * (MOD - MOD / i) % MOD;
     35     }
     36 }
     37 struct Node {
     38     int op, x, y;
     39 } que[100010];
     40 int main() {
     41     //freopen("a.in", "r", stdin);
     42     init();
     43     int n, q;
     44     scanf("%d%d", &n, &q);
     45     for(int i = 1; i <= q; ++ i) {
     46           int op, x = 0, y = 0;
     47           scanf("%d", &op);
     48           if(op == 1) {
     49               scanf("%d%d", &x, &y);
     50               y %= MOD;
     51               y = (y + MOD) % MOD;
     52           }
     53           else if(2 <= op && op <= 5) {
     54               scanf("%d", &x);
     55               if(op != 5) {
     56                   x %= MOD;
     57                   x = (x + MOD) % MOD;
     58               }
     59           }
     60           //cerr << op << " " << x << " " << y << endl;
     61            que[i] = (Node){op, x, y};
     62        }
     63        int mul = 1, add = 0, sum = 0;
     64     int t;
     65     scanf("%d", &t);
     66     int Ans = 0, cnt = 0;
     67     while(t --) {
     68         int A, B;
     69         scanf("%d%d", &A, &B);
     70         //cerr << A << B << endl;
     71         for(int i = 1; i <= q; ++ i) {
     72             ++ cnt;
     73             int id = (A + 1ll * i * B) % q + 1;
     74             int op = que[id].op, x = que[id].x, y = que[id].y;
     75             if(op == 1) {
     76                 int ry = 1ll * (y - add + MOD) * inv[mul] % MOD;
     77                 int d = hash::upd(x, ry, cnt);
     78                 sum += d;
     79                 if(sum >= MOD) sum -= MOD;
     80                 if(sum < 0) sum += MOD;
     81             }
     82             else if(op == 2) {
     83                 add += x;
     84                 if(add >= MOD) add -= MOD;
     85             }
     86             else if(op == 4 || (op == 3 && x == 0)) {
     87                 sum = 1ll * n * x % MOD;
     88                 add = 0, mul = 1;
     89                 hash::All = (x + MOD) % MOD;
     90                 hash::CLO = cnt;
     91             }
     92             else if(op == 3) {
     93                 mul = 1ll * mul * x % MOD;
     94                 add = 1ll * add * x % MOD;
     95             }
     96             else if(op == 5) {
     97                 int res = hash::query(x);
     98                 res = (1ll * res * mul + add) % MOD;
     99                 Ans += res;
    100                 if(Ans >= MOD) Ans -= MOD;
    101             }
    102             else {
    103                 int res = (1ll * sum * mul + 1ll * n * add) % MOD;
    104                 Ans += res;
    105                 if(Ans >= MOD) Ans -= MOD;
    106             }
    107             if(mul < 0) mul += MOD;
    108             if(add < 0) add += MOD;
    109             if(sum < 0) sum += MOD;
    110             //cerr << sum << endl;
    111         }
    112     }
    113     printf("%d
    ", Ans);
    114 }
    View Code

    SDOI2019 热闹的聚会与尴尬的聚会

    一道构造好题。

    $lfloorfrac{n}{p+1} floor leq q$可以推出$(p+1)(q+1)>n$。

    每次枚举当前图中度数最小的点$x$,删除$x$以及与$x$相邻的点。

    设总共会删除$q$次,显然有$sum_{i=1}^q (d_i+1) = n$。

    对于每次枚举的$x$度数中的最大值$mxd$,一定可以找到一个$p=mxd$的构造方案。

    所以有$sum_{i=1}^q (d_i+1)leq mxd*q$。

    稍加推倒可以证明如果找到$p=mxd$的构造方案,那么可以满足$(p+1)(q+1)>n$。

    构造的方案即为当$d_x=mxd$时,当前图中剩余的全部点。

    显然可以发现除了$x$以外,其他的点$y$满足$mxd leq d_y$。

    用$set$维护即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct Edge{
     4     int u, v, Next;
     5 } G[200010];
     6 int head[100010], tot;
     7 int d[100010];
     8 struct Node{
     9     int D, x;
    10     inline bool operator < (const Node& rhs) const{
    11         return D < rhs.D || (D == rhs.D && x < rhs.x);
    12     }
    13 };
    14 set<Node> S;
    15 inline void add(int u, int v) {
    16     G[++ tot] = (Edge){u, v, head[u]};
    17     head[u] = tot;
    18 }
    19 int ans1[100010], t1;
    20 int ans2[100010], t2;
    21 inline void solve() {
    22     int n, m;
    23     scanf("%d%d", &n, &m);
    24     tot = 0;
    25     for(int i = 1; i <= n; ++ i) {
    26         head[i] = -1;
    27         d[i] = 0;
    28     }
    29     for(int i = 1; i <= m; ++ i) {
    30         int u, v;
    31         scanf("%d%d", &u, &v);
    32         add(u, v), add(v, u);
    33         ++ d[u], ++ d[v];
    34     }
    35     for(int i = 1; i <= n; ++ i) {
    36         S.insert((Node){d[i], i});
    37     }
    38     int mxd = 0, pos;
    39     t1 = t2 = 0;
    40     while(!S.empty()) {
    41         set<Node> :: iterator t = S.begin();
    42         //cerr <<  "element " << t -> x << endl;
    43         S.erase(t);
    44         if(t -> D > mxd) {
    45             mxd = t -> D;
    46             pos = t1;
    47         }
    48         int x = t -> x;
    49         ans2[++ t2] = x;
    50         ans1[++ t1] = x;
    51         for(int i = head[x]; i != -1; i = G[i].Next) {
    52             t = S.find((Node){d[G[i].v], G[i].v});
    53             
    54             if(t == S.end()) continue;
    55             //cerr << x << " " << G[i].v << endl;
    56             int X = t -> x;
    57             ans1[++ t1] = X;
    58             S.erase(t);
    59             for(int j = head[X]; j != -1; j = G[j].Next) {
    60                 set<Node> :: iterator it = S.find((Node){d[G[j].v], G[j].v});
    61                 if(it == S.end()) continue;
    62                 S.erase(it);
    63                 S.insert((Node){-- d[G[j].v], G[j].v});
    64             }
    65         }
    66     }
    67     printf("%d ", t1 - pos);
    68     for(int i = pos + 1; i <= t1; ++ i) {
    69         printf("%d ", ans1[i]);
    70     }
    71     puts("");
    72     printf("%d ", t2);
    73     for(int i = 1; i <= t2; ++ i) {
    74         printf("%d ", ans2[i]);
    75     }
    76     puts("");
    77 }
    78 int main() {
    79     int T;
    80     scanf("%d", &T);
    81     while(T --) {
    82         solve();
    83     }
    84 }
    View Code

    SDOI2019 移动金币

    首先进行模型转化。题目等价于:

    有$m+1$堆棋子,棋子总数$n-m$,每次把一堆中的若干棋子移动到前一堆中,求先手必胜方案数。

    也就是求阶梯$NIM$的先手必胜方案数,即奇数项异或和不为$0$的方案数。

    容斥一下,变为询问异或和为$0$的方案数。

    $f_{i,j}$表示前$i$位确定,和为$j$的方案数。

    $g_{i,j,k}$表示前$i$个堆,和为$j$,异或和为$k$的方案数。

    注意本题中第一堆棋子是无用的,即为一开始就在第$0$堆中,需从第二堆开始编号。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define MOD 1000000009
     4 #define mxbit 19
     5 int f[60][150010]; // first i bit  sum = j
     6 int g[60][60][2]; // first i pile sum = j  xor_sum = k;
     7 inline void Add(int &x, int y) {
     8     x += y;
     9     if(x >= MOD) x -= MOD;
    10 }
    11 inline int Power(int x, int y) {
    12     int ret = 1;
    13     while(y) {
    14         if(y & 1) ret = 1ll * ret * x % MOD;
    15         x = 1ll * x * x % MOD;
    16         y >>= 1; 
    17     }
    18     return ret;
    19 }
    20 inline int C(int n, int m) {
    21     int ret = 1;
    22     for(int i = n - m + 1; i <= n; ++ i) {
    23         ret = 1ll * ret * i % MOD;
    24     }
    25     for(int i = 1; i <= m; ++ i) {
    26         ret = 1ll * ret * Power(i, MOD - 2) % MOD;
    27     }
    28     return ret;
    29 }
    30 inline void calc_g(int m, int n) {
    31     g[0][0][0] = 1;
    32     for(int i = 0; i < m; ++ i) {
    33         for(int j = 0; j <= i; ++ j) {
    34             for(int k = 0; k <= 1; ++ k) {
    35                 if(i & 1) {
    36                     for(int w = 0; w <= 1; ++ w) {
    37                         Add(g[i + 1][j + w][k ^ w], g[i][j][k]);
    38                     }
    39                 }
    40                 else {
    41                     for(int w = 0; w <= 1; ++ w) {
    42                         Add(g[i + 1][j + w][k], g[i][j][k]);
    43                     }
    44                 }
    45             }
    46         }
    47     }
    48 }
    49 inline void calc_f(int m, int n) {
    50     f[0][0] = 1;
    51     for(int i = 0; i < mxbit; ++ i) {
    52         for(int j = 0; j <= n; ++ j) if(f[i][j]) {
    53             for(int k = 0; k <= m && k * (1 << i) + j <= n; ++ k) {
    54                 Add(f[i + 1][j + k * (1 << i)], 1ll * f[i][j] * g[m][k][0] % MOD);
    55             }
    56         }
    57     }
    58 }
    59 int main() {
    60     int n, m;
    61     scanf("%d%d", &n, &m);
    62     int All = C(n, m);
    63     calc_g(m + 1, n - m);
    64     calc_f(m + 1, n - m);
    65     All -= f[mxbit][n - m];
    66     if(All < 0) All += MOD;
    67     printf("%d
    ", All);
    68 }
    View Code

    SDOI2017 数字表格

    题目就是要求$$prod_d^{n} f(d)^{g(d,n,m)}$$

    其中$$g(d,n,m)=sum_i^{lfloorfrac{n}{d} floor}sum_j^{lfloorfrac{m}{d} floor}[gcd(i,j)=1]$$

    显然莫比乌斯反演得到$$prod_d^{n} f(d)^{sum_k^{lfloorfrac{n}{d} floor} lfloorfrac{n}{kd} floorlfloorfrac{m}{kd} floor mu(k)}$$

    令$u=kd$换元得到$$prod_u^n prod_{d|u} f(d)^{lfloorfrac{n}{u} floorlfloorfrac{m}{u} floormu(frac{u}{d})}$$

    预处理后每次$O(sqrt{n})$求答案

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define M 1000010
     4 #define MOD 1000000007
     5 int mu[M], pri[M], tot;
     6 bool vis[M];
     7 int f[M];
     8 int pre[M], inv[M], g[M];
     9 inline int Power(int x, int y) {
    10     int ret = 1;
    11     while(y) {
    12         if(y & 1) ret = 1ll * ret * x % MOD;
    13         x = 1ll * x * x % MOD;
    14         y >>= 1;
    15     }
    16     return ret;
    17 }
    18 inline void init() {
    19     mu[1] = 1;
    20     f[1] = 1;
    21     for(int i = 2; i <= M - 10; ++ i) {
    22         f[i] = f[i - 1] + f[i - 2];
    23         if(f[i] >= MOD) f[i] -= MOD;
    24     }
    25     for(int i = 2; i <= M - 10; ++ i) {
    26         if(!vis[i]) {
    27             pri[++ tot] = i;
    28             mu[i] = -1;
    29         }
    30         for(int j = 1; j <= tot; ++ j) {
    31             if(i * pri[j] > M - 10) {
    32                 break;
    33             }
    34             vis[i * pri[j]] = 1;
    35             if(i % pri[j] == 0) {
    36                 mu[i * pri[j]] = 0;
    37                 break;
    38             }
    39             else mu[i * pri[j]] = -mu[i];
    40         }
    41     }
    42     pre[0] = inv[0] = 1;
    43     for(int i = 1; i <= M - 10; ++ i) {
    44         pre[i] = 1;
    45     }
    46     for(int i = 1; i <= M - 10; ++ i) {
    47         int invf = Power(f[i], MOD - 2);
    48         for(int j = i; j <= M - 10; j += i) {
    49             if(mu[j / i] == -1) {
    50                 pre[j] = 1ll * pre[j] * invf % MOD;
    51             }
    52             else if(mu[j / i] == 1) {
    53                 pre[j] = 1ll * pre[j] * f[i] % MOD;
    54             }
    55         }
    56     }
    57     for(int i = 1; i <= M - 10; ++ i) {
    58         pre[i] = 1ll * pre[i - 1] * pre[i] % MOD;
    59         inv[i] = Power(pre[i], MOD - 2);
    60     }
    61 }
    62 inline void solve(int n, int m) {
    63     int res = 1, lst;
    64     for(int i = 1; i <= n && i <= m; i = lst + 1) {
    65         lst = min(n / (n / i), m / (m / i));
    66         int tmp = 1ll * (n / i) * (m / i) % (MOD - 1);
    67         res = 1ll * res * Power(1ll * pre[lst] * inv[i - 1] % MOD, tmp) % MOD;
    68     }
    69     printf("%d
    ", res);
    70 }
    71 int main() {
    72     init();
    73     int T;
    74     scanf("%d", &T);
    75     while(T --) {
    76         int n, m;
    77         scanf("%d%d", &n, &m);
    78         solve(n, m);
    79     }
    80 }
    View Code

    SDOI2017 序列计数

    题目比较基础,容斥之后就变成了矩阵优化dp

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define MOD 20170408
     4 bool vis[20000010];
     5 int pri[2000010], tot;
     6 int a[500]; // with prime
     7 int b[500]; // without prime
     8 int n, m, p;
     9 inline void init() {
    10     vis[1] = 1;
    11     for(int i = 2; i <= m; ++ i) {
    12         if(!vis[i]) {
    13             pri[++ tot] = i;
    14         }
    15         for(int j = 1; j <= tot; ++ j) {
    16             if(i * pri[j] > m) break;
    17             vis[i * pri[j]] = 1;
    18             if(i % pri[j] == 0) break;
    19         }
    20     }
    21     int q = 0;
    22     for(int i = 1; i <= m; ++ i) {
    23         ++ q;
    24         if(q == p) q = 0;
    25         ++ a[q];
    26         if(vis[i]) ++ b[q];
    27     }
    28     for(int i = 0; i < p; ++ i) {
    29         a[i] %= MOD;
    30         b[i] %= MOD;
    31     }
    32 }
    33 int o[110][110];
    34 int f[110], g[110];
    35 int c[110], C[110][110];
    36 inline void Do(int *F, int *a) {
    37     F[0] = 1;
    38     memset(o, 0, sizeof(o));
    39     for(int i = 0; i < p; ++ i) {
    40         for(int j = 0; j < p; ++ j) {
    41             o[i][j] = a[(j - i + p) % p];
    42         }
    43     }
    44     int y = n;
    45     while(y) {
    46         if(y & 1) {
    47             for(int i = 0; i < p; ++ i) {
    48                 c[i] = 0;
    49             }
    50             for(int i = 0; i < p; ++ i) {
    51                 for(int j = 0; j < p; ++ j) {
    52                     c[j] += 1ll * F[i] * o[i][j] % MOD;
    53                     if(c[j] >= MOD) c[j] -= MOD;
    54                 }
    55             }
    56             for(int i = 0; i < p; ++ i) {
    57                 F[i] = c[i];
    58             }
    59         }
    60         y >>= 1;
    61         for(int i = 0; i < p; ++ i) {
    62             for(int j = 0; j < p; ++ j) {
    63                 C[i][j] = 0;
    64                 for(int k = 0; k < p; ++ k) {
    65                     C[i][j] += 1ll * o[i][k] * o[k][j] % MOD;
    66                 }
    67                 C[i][j] %= MOD;
    68             }
    69         }
    70         for(int i = 0; i < p; ++ i) {
    71             for(int j = 0; j < p; ++ j) {
    72                 o[i][j] = C[i][j];
    73             }
    74         }
    75     }
    76 }
    77 int main() {
    78     scanf("%d%d%d", &n, &m, &p);
    79     init();        
    80     Do(f, a), Do(g, b);
    81     printf("%d
    ", (f[0] - g[0] + MOD) % MOD);
    82 }
    View Code

    一个人的高三楼 

    题目就是要求$A*B^k$,$B(x)=1+x+x^2+……+x^n$

    注意到$B^k$可以用组合数计算,套个NTT就行

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define M 1000010
     4 #define LL long long
     5 #define MOD 998244353
     6 inline int Power(int x, int y) {
     7     int ret = 1;
     8     while(y) {
     9         if(y & 1) ret = 1ll * ret * x % MOD;
    10         x = 1ll * x * x % MOD;
    11         y >>= 1;
    12     }
    13     return ret;
    14 }
    15 int N;
    16 int a[M], b[M], rev[M], w[M];
    17 inline void NTT(int *a) {
    18     for(int i = 0; i < N; ++ i) {
    19         if(rev[i] > i) {
    20             swap(a[rev[i]], a[i]);
    21         }
    22     }
    23     for(int d = 1, t = (N >> 1); d < N; d <<= 1, t >>= 1) {
    24         for(int i = 0; i < N; i += (d << 1)) {
    25             for(int j = 0; j < d; ++ j) {
    26                 int tmp = 1ll * w[t * j] * a[i + j + d] % MOD;
    27                 a[i + j + d] = (a[i + j] - tmp + MOD) % MOD;
    28                 a[i + j] = (a[i + j] + tmp) % MOD;
    29             }
    30         }
    31     }
    32 }
    33 int main() {
    34     int n; LL K;
    35     scanf("%d%lld", &n, &K);
    36     for(int i = 0; i < n; ++ i) {
    37         scanf("%d", &a[i]);
    38     }
    39     b[0] = 1;
    40     for(int i = 1; i < n; ++ i) {
    41         b[i] = 1ll * b[i - 1] * ((K + i - 1) % MOD) % MOD * Power(i, MOD - 2) % MOD;
    42     }
    43     N = 1; int L = 0;
    44     for(; N <= 2 * n; N <<= 1, ++ L);
    45     for(int i = 0; i < N; ++ i) {
    46         rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (L - 1));
    47     }
    48     w[0] = 1; w[1] = Power(3, (MOD - 1) / N);
    49     for(int i = 2; i < N; ++ i) {
    50         w[i] = 1ll * w[i - 1] * w[1] % MOD;
    51     }
    52     NTT(a), NTT(b);
    53     for(int i = 0; i < N; ++ i) {
    54         a[i] = 1ll * a[i] * b[i] % MOD;
    55     }
    56     w[1] = Power(w[1], MOD - 2);
    57     for(int i = 2; i < N; ++ i) {
    58         w[i] = 1ll * w[i - 1] * w[1] % MOD;
    59     }
    60     NTT(a);
    61     int inv = Power(N, MOD - 2);
    62     for(int i = 0; i < N; ++ i) {
    63         a[i] = 1ll * a[i] * inv % MOD;
    64     }
    65     for(int i = 0; i < n; ++ i) {
    66         printf("%d
    ", a[i]);
    67     }
    68 }
    View Code

    TJOI2017 唱、跳、rap和篮球

    容斥之后,就是求选$i$个连续四个位置的方案数$f(i)$乘剩下的数的选择方案$g(n-4*i,i)$。

    连续四个就等于$n-3*i$的数列中选$i$个,再把这$i$个后面每个都填上$3$个。

    所以有$f(i)=C(n-3*i,i)$。

    $g(n-4*t,t)=[x^{n-4*t}]sum_{i=0}^{a-t}sum_{j=0}^{b-t}sum_{k=0}^{c-t}sum_{w=0}^{d-t}frac{n!}{i!j!k!w!}*x^{i+j+k+w}$

    $NTT$优化复杂度$O(n^2logn)$

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define MOD 998244353
      4 int n, A, B, C, D;
      5 int lim;
      6 int fac[1010], inv[1010], f[1010];
      7 int N;
      8 int rev[10010];
      9 int w[10010], a[10010], b[10010], c[10010], d[10010];
     10 inline int Power(int x, int y) {
     11     int ret = 1;
     12     while(y) {
     13         if(y & 1) ret = 1ll * ret * x % MOD;
     14         x = 1ll * x * x % MOD; y >>= 1;
     15     }
     16     return ret;
     17 }
     18 inline int CC(int x, int y) {
     19     return 1ll * fac[x] * inv[y] % MOD * inv[x - y] % MOD;
     20 }
     21 inline void init() {
     22     fac[0] = fac[1] = 1;
     23     inv[0] = inv[1] = 1;
     24     for(int i = 2; i <= 1000; ++ i) {
     25         fac[i] = 1ll * fac[i - 1] * i % MOD;
     26         inv[i] = 1ll * (MOD - MOD / i) * inv[MOD % i] % MOD;
     27     }
     28     for(int i = 1; i <= 1000; ++ i) {
     29         inv[i] = 1ll * inv[i - 1] * inv[i] % MOD;
     30     }
     31     for(int i = 0; i <= lim; ++ i) {
     32         f[i] = CC(n - 3 * i, i);
     33     }
     34 }
     35 inline void NTT(int *a) {
     36     for(int i = 0; i < N; ++ i) {
     37         if(rev[i] > i) {
     38             swap(a[rev[i]], a[i]);
     39         }
     40     }
     41     for(int d = 1, t = (N >> 1); d < N; d <<= 1, t >>= 1) {
     42         for(int i = 0; i < N; i += (d << 1)) {
     43             for(int j = 0; j < d; ++ j) {
     44                 int tmp = 1ll * w[t * j] * a[i + j + d] % MOD;
     45                 a[i + j + d] = (a[i + j] - tmp + MOD) % MOD;
     46                 a[i + j] = (a[i + j] + tmp) % MOD;
     47             }
     48         }
     49     }
     50 }
     51 inline int Do(int n, int m) {
     52     int la = A - m, lb = B - m, lc = C - m, ld = D - m;
     53     la = min(la, n); lb = min(lb, n);
     54     lc = min(lc, n); ld = min(ld, n);
     55     int tot = max(la + lb + lc + ld, n);
     56     N = 1; int L = 0;
     57     for(; N <= tot; N <<= 1, ++ L);
     58     for(int i = 0; i < N; ++ i) {
     59         rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (L - 1));
     60     }
     61     for(int i = 0; i < N; ++ i) {
     62         a[i] = b[i] = c[i] = d[i] = 0;
     63     }
     64     for(int i = 0; i <= la; ++ i) {
     65         a[i] = inv[i];
     66     }
     67     for(int i = 0; i <= lb; ++ i) {
     68         b[i] = inv[i];
     69     }
     70     for(int i = 0; i <= lc; ++ i) {
     71         c[i] = inv[i];
     72     }
     73     for(int i = 0; i <= ld; ++ i) {
     74         d[i] = inv[i];
     75     }
     76     w[0] = 1; w[1] = Power(3, (MOD - 1) / N);
     77     for(int i = 2; i < N; ++ i) {
     78         w[i] = 1ll * w[i - 1] * w[1] % MOD;
     79     }
     80     NTT(a), NTT(b), NTT(c), NTT(d);
     81     for(int i = 0; i < N; ++ i) {
     82         a[i] = 1ll * a[i] * b[i] % MOD * c[i] % MOD * d[i] % MOD;
     83     }
     84     w[1] = Power(w[1], MOD - 2);
     85     for(int i = 2; i < N; ++ i) {
     86         w[i] = 1ll * w[i - 1] * w[1] % MOD;
     87     }
     88     NTT(a);
     89     return 1ll * a[n] * Power(N, MOD - 2) % MOD * fac[n] % MOD;
     90 }
     91 int main() {
     92     scanf("%d%d%d%d%d", &n, &A, &B, &C, &D);
     93     lim = min(n / 4, min(A, min(B, min(C, D))));
     94     init();
     95     int res = 0;
     96     for(int i = 0; i <= lim; ++ i) {
     97         int op = 1;
     98         if(i & 1) op = -1;
     99         res += 1ll * op * f[i] * Do(n - 4 * i, i) % MOD;
    100         if(res >= MOD) res -= MOD;
    101         if(res < 0) res += MOD;
    102     }
    103     printf("%d
    ", res);
    104 }
    View Code
  • 相关阅读:
    hdu 1281 棋盘游戏(二分匹配)
    UVA 12545 Bits Equalizer
    算法之匈牙利算法
    I题 hdu 1234 开门人和关门人
    H题 hdu 2520 我是菜鸟,我怕谁
    G题 hdu 1466 计算直线的交点数
    F题 hdu 1431 素数回文
    E题hdu 1425 sort
    D题 hdu 1412 {A} + {B}
    有12个球,外形相同,其中一个小球的质量与其他11个不同,给一个天平,需要几次把这个小球找出来并且求出这个小球是比其他的轻还是重
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/11431853.html
Copyright © 2020-2023  润新知