zoukankan      html  css  js  c++  java
  • BZOJ3992 [SDOI2015]序列统计

    首先对于m,求出它的原根g,则$$prod_{i = 1} ^ {n} x_i = g^{sum_{i = 1} ^ {n} ind[x_i]}$$

    于是就变成加法的问题了,搞出母函数$f(x)$,于是变成$f(x)^{|n|}$的第m项是多少。。。

    又注意到要模一个数。。。就只能NTT了QAQ

      1 /**************************************************************
      2     Problem: 3992
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:4064 ms
      7     Memory:1260 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <bitset>
     13  
     14 using namespace std;
     15 typedef long long ll;
     16 const int N = 16405;
     17 const int G = 3;
     18 const int mod = 1004535809;
     19  
     20 int n, m, d, tar, S, g;
     21 int ind[N];
     22 int w[2][N];
     23 int p[N], cnt_p;
     24 bitset <N> is_p;
     25  
     26 inline int read();
     27  
     28 ll pow(ll x, int y, int p) {
     29     static ll res;
     30     res = 1;
     31     while (y) {
     32         if (y & 1) res = res * x % p;
     33         x = x * x % p, y >>= 1;
     34     }
     35     return res;
     36 }
     37  
     38 inline int get_inv(int x, int mod) {
     39     return pow(x, mod - 2, mod);
     40 }
     41  
     42 inline void pre() {
     43     int i, t;
     44     w[0][0] = w[0][d] = 1;
     45     t = pow(G, (mod - 1) / d, mod);
     46     for (i = 1; i < d; ++i) w[0][i] = 1ll * w[0][i - 1] * t % mod;
     47     for (i = 0; i <= d; ++i) w[1][i] = w[0][d - i];
     48 }
     49  
     50 void NTT(int *x, int k, int v) {
     51     int i, j, l, tmp;
     52     for (i = j = 0; i < k; ++i) {
     53         if (i > j) swap(x[i], x[j]);
     54         for (l = k >> 1; (j ^= l) < l; l >>= 1);
     55     }
     56     for (i = 2; i <= k; i <<= 1)
     57         for (j = 0; j < k; j += i)
     58             for (l = 0; l < i >> 1; ++l) {
     59                 tmp = 1ll * x[j + l + (i >> 1)] * w[v][k / i * l] % mod;
     60                 x[j + l + (i >> 1)] = (1ll * x[j + l] - tmp + mod) % mod;
     61                 x[j + l] = (1ll * x[j + l] + tmp) % mod;
     62             }
     63 }
     64  
     65 struct data {
     66     int a[N];
     67     data() {
     68         memset(a, 0, sizeof(a));
     69     }
     70      
     71     inline void one() {
     72         memset(a, 0, sizeof(a));
     73         a[0] = 1;
     74     }
     75      
     76     inline int& operator [] (int x) {
     77         return a[x];
     78     }
     79      
     80     inline data& operator *= (const data &t) {
     81         static int b[N], i, inv;
     82         memcpy(b, t.a, sizeof(b));
     83         NTT(a, d, 0), NTT(b, d, 0);
     84         for (i = 0; i < d; ++i) a[i] = 1ll * a[i] * b[i] % mod;
     85         NTT(a, d, 1);
     86         for (i = m - 1; i <= m - 2 << 1; ++i)
     87             (a[i - (m - 1)] += a[i]) %= mod, a[i] = 0;
     88         for (inv = get_inv(d, mod), i = 0; i <= m - 2; ++i)
     89             a[i] = 1ll * a[i] * inv % mod;
     90         return *this;
     91     }
     92      
     93     friend inline data pow(data &x, int y) {
     94         static data res;
     95         res.one();
     96         while (y) {
     97             if (y & 1) res *= x;
     98             x *= x, y >>= 1;
     99         }
    100         return res;
    101     }
    102 } a;
    103  
    104 inline void get_prime() {
    105     is_p.set();
    106     int i, j, k;
    107     for (i = 2; i < N; ++i) {
    108         if (is_p[i]) p[++cnt_p] = i;
    109         for (j = 1; j <= cnt_p; ++j) {
    110             if ((k = i * p[j]) >= N) break;
    111             is_p[k] = 0;
    112             if (i % p[j] == 0) break;
    113         }
    114     }
    115 }
    116  
    117 int di[100], cnt_d;
    118 inline void divide(int n) {
    119     static int i, t;
    120     for (cnt_d = 0, t = n, i = 1; p[i] * p[i] <= t; ++i)
    121         if (t % p[i] == 0) {
    122             di[++cnt_d] = p[i];
    123             while (t % p[i] == 0) t /= p[i];
    124         }
    125     if (t > 1) di[++cnt_d] = t;
    126 }
    127  
    128 inline int get_g(int P) {
    129     static int g, i, f;
    130     divide(P - 1);
    131     for (g = 2; g < P; ++g) {
    132         for (i = f = 1; i <= cnt_d; ++i)
    133             if (pow(g, (P - 1) / di[i], P) == 1) {
    134                 f = 0;
    135                 break;
    136             }
    137         if (f) return g;
    138     }
    139 }
    140  
    141 int main() {
    142     int i, x, now;
    143     n = read(), m = read(), tar = read(), S = read();
    144     for (d = 1; d <= m << 1; d <<= 1);
    145     pre(), get_prime(), g = get_g(m);
    146     for (i = 0, now = 1; i < m - 1; ++i, now = now * g % m)
    147         ind[now] = i;
    148     for (i = 1; i <= S; ++i) {
    149         if (x = read()) a[ind[x]] = 1;
    150     }
    151     printf("%d
    ", pow(a, n)[ind[tar]]);
    152     return 0;
    153 }
    154  
    155 inline int read() {
    156     static int x;
    157     static char ch;
    158     x = 0, ch = getchar();
    159     while (ch < '0' || '9' < ch)
    160         ch = getchar();
    161     while ('0' <= ch && ch <= '9') {
    162         x = x * 10 + ch - '0';
    163         ch = getchar();
    164     }
    165     return x;
    166 }
    View Code

     (p.s. 1004535809这货的原根是3)

    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    关联原理说明
    一个软件测试工程师的学习体验
    缺陷漏测分析:测试过程改进
    自动化测试的7个步骤
    ACM题目————Subsequence
    ACM题目————Aggressive cows
    ACM题目————列变位法解密
    C++TSL之map容器(悲伤的故事)
    ACM题目————二叉树最大宽度和高度
    ACM题目————装箱问题
  • 原文地址:https://www.cnblogs.com/rausen/p/4451888.html
Copyright © 2011-2022 走看看