zoukankan      html  css  js  c++  java
  • 【NTT】bzoj3992: [SDOI2015]序列统计

    板子题都差点不会了

    Description

    小C有一个集合S,里面的元素都是小于M的非负整数。他用程序编写了一个数列生成器,可以生成一个长度为N的数
    列,数列中的每个数都属于集合S。小C用这个生成器生成了许多这样的数列。但是小C有一个问题需要你的帮助:
    给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个。小C认为
    ,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi。另外,小C认为这个问题的答案可能很大
    ,因此他只需要你帮助他求出答案mod 1004535809的值就可以了。

    Input

    一行,四个整数,N、M、x、|S|,其中|S|为集合S中元素个数。
    第二行,|S|个整数,表示集合S中的所有元素。
    1<=N<=10^9,3<=M<=8000,M为质数
    0<=x<=M-1,输入数据保证集合S中元素不重复x∈[1,m-1]

    集合中的数∈[0,m-1]

    Output

    一行,一个整数,表示你求出的种类数mod 1004535809的值。


    题目分析

    用$f_{i,j}$表示选了$i$个数乘积为$j$的方案数,不难得到式子$f_{2i,j}=sumlimits_{a*bequiv j(mod m)}f_{i,a} imes f_{i,b}$

    对于乘法转加法,常见套路就是取对数。那么这里在模意义下,注意到原根$g$有很好的性质:$g^0,g^1,cdots ,g^{m-2}$可以取遍$[1cdots m-1]$,因此令$jequiv g^A(mod m)$,不妨用$A$代替$j$,以此类推。所以剩下的就是一个多项式快速幂的过程了,最终答案就是$f_x$的系数。

    中途写错两个地方:为$[1cdots m-1]$内元素按$g^i$标号时,写成遍历$[0cdots m-1]$(这里整体下标减一。说到底还是对式子不熟练。);给$x$重标号时候,写成 if (x==tar&&!fl) tar = x, fl = 1; ……

     1 #include<bits/stdc++.h>
     2 #define MO 1004535809
     3 const int maxn = 50035;
     4 
     5 int T,n,m,tar,len,dt,inv3,invn,ort;
     6 int f[maxn],g[maxn],cov[maxn],tmp1[maxn],tmp2[maxn];
     7 bool vis[maxn];
     8 
     9 int read()
    10 {
    11     char ch = getchar();
    12     int num = 0, fl = 1;
    13     for (; !isdigit(ch); ch=getchar())
    14         if (ch=='-') fl = -1;
    15     for (; isdigit(ch); ch=getchar())
    16         num = (num<<1)+(num<<3)+ch-48;
    17     return num*fl;
    18 }
    19 int qmi(int a, int b, int p)
    20 {
    21     int ret = 1;
    22     for (; b; b>>=1, a=1ll*a*a%p)
    23         if (b&1) ret = 1ll*ret*a%p;
    24     return ret;
    25 }
    26 int fndRoot()
    27 {
    28     int fac[10035], tot = 0, pos = m-1;
    29     for (int i=2; i*i<=pos; i++)
    30         if (pos%i==0){
    31             fac[++tot] = i;
    32             while (pos%i==0) pos /= i;
    33         }
    34     if (pos!=1) fac[++tot] = pos;
    35     pos = m-1;
    36     for (int i=2; i<=pos; i++)
    37     {
    38         bool chk = true;
    39         for (int j=1; j<=tot&&chk; j++)
    40             if (qmi(i, pos/fac[j], m)==1) chk = false;
    41         if (chk) return i;
    42     }
    43     return -1;
    44 }
    45 void NTT(int *a, int opt)
    46 {
    47     for (int i=0; i<len; i++)
    48         if (i < cov[i]) std::swap(a[i], a[cov[i]]);
    49     for (int i=1; i<len; i<<=1)
    50     {
    51         int Wn = qmi(3, (MO-1)/(i<<1), MO);
    52         if (opt==-1) Wn = qmi(inv3, (MO-1)/(i<<1), MO);
    53         for (int j=0, p=i<<1; j<len; j+=p)
    54         {
    55             int w = 1;
    56             for (int k=0; k<i; k++, w=1ll*w*Wn%MO)
    57             {
    58                 int valx = a[j+k], valy = 1ll*w*a[i+j+k]%MO;
    59                 a[j+k] = (valx+valy)%MO, a[i+j+k] = (valx-valy+MO)%MO;
    60             }
    61         }
    62     }
    63     if (opt==-1) for (int i=0; i<len; i++) a[i] = 1ll*a[i]*invn%MO;
    64 }
    65 void mult(int *a, int *b)
    66 {
    67     for (int i=0; i<len; i++) tmp1[i] = a[i], tmp2[i] = b[i];
    68     NTT(tmp1, 1), NTT(tmp2, 1);
    69     for (int i=0; i<len; i++) tmp1[i] = 1ll*tmp1[i]*tmp2[i]%MO;
    70     NTT(tmp1, -1);
    71     for (int i=0; i<m-1; i++) a[i] = (tmp1[i]+tmp1[i+m-1])%MO;
    72 }
    73 int main()
    74 {
    75     T = read(), m = read(), tar = read(), n = read();
    76     inv3 = qmi(3, MO-2, MO), ort = fndRoot();
    77     for (int i=1; i<=n; i++) vis[read()] = true;
    78     for (int i=0, x=1, fl=0; i<m-1; i++, x=1ll*x*ort%m)
    79     {
    80         if (vis[x]) g[i] = 1;
    81         if (x==tar&&!fl) tar = i, fl = 1;
    82     }
    83     for (len=1; len<=(m-1)<<1; len<<=1) ++dt;
    84     for (int i=0; i<len; i++)
    85         cov[i] = (cov[i>>1]>>1)|((i&1)<<(dt-1));
    86     f[0] = 1, invn = qmi(len, MO-2, MO);
    87     for (; T; T>>=1, mult(g, g))
    88         if (T&1) mult(f, g);
    89     printf("%d
    ",f[tar]);
    90     return 0;
    91 }

    END

  • 相关阅读:
    信息系统项目管理系列之十:项目人力资源管理
    信息系统项目管理系列之六:项目范围管理
    记大型商业软件<<国土档案管理信息系统>>之系统简介
    信息系统项目管理系列之九:项目质量管理
    ORACLE常见问题一千问(提供下载)(不怕学不成、就怕心不诚!)
    (推荐)(提供下载)ORACLE常见问题一千问(不怕学不成、就怕心不诚!)
    [推荐]ORACLE SQL:经典查询练手第四篇(不懂装懂,永世饭桶!)
    [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)
    [提供源码下载]在大型软件中用Word做报表:书签的应用(提供一种思路)
    (推荐一个超好的JS函数库)S.Sams Lifexperience ScriptClassLib
  • 原文地址:https://www.cnblogs.com/antiquality/p/10554466.html
Copyright © 2011-2022 走看看