传送门

生成函数简单题。

题意:给出一个集合A={a1,a2,...as}A=\{a_1,a_2,...a_s\}A={a1​,a2​,...as​},所有数都在[0,m−1][0,m-1][0,m−1]之间,mmm是一个质数,求满足全部由这个集合里的组成且长度为nnn且所有数之积与xxx在模mmm意义下相同的数列总数。


思路:对a1,a2,..,as,xa_1,a_2,..,a_s,xa1​,a2​,..,as​,x全部化成gb1,gb2,...gbs,gyg^{b_1},g^{b_2},...g^{b_s},g^{y}gb1​,gb2​,...gbs​,gy,然后就转乘法为加法。

于是只用求x1+x2+...+xn≡ymod  m−1x_1+x_2+...+x_n\equiv y\mod m-1x1​+x2​+...+xn​≡ymodm−1,其中xi∈{b1,b2,...bs}x_i\in\{b_1,b_2,...b_s\}xi​∈{b1​,b2​,...bs​}的方案数。

对于xix_ixi​可以构造出生成函数1+xb1+xb2+...+xbs1+x^{b_1}+x^{b_2}+...+x^{b_s}1+xb1​+xb2​+...+xbs​,于是答案的生成函数就是(1+xb1+xb2+...+xbs)n(1+x^{b_1}+x^{b_2}+...+x^{b_s})^n(1+xb1​+xb2​+...+xbs​)n,考虑到nnn很大可以用快速幂+nttnttntt解决。

注意特判ai=0a_i=0ai​=0的情况以及每次nttnttntt完了之后要重新把多项式的最高次数控制为m−2m-2m−2

代码:

  1. #include<bits/stdc++.h>
  2. #define ri register int
  3. using namespace std;
  4. inline int read(){
  5. int ans=0;
  6. char ch=getchar();
  7. while(!isdigit(ch))ch=getchar();
  8. while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
  9. return ans;
  10. }
  11. typedef long long ll;
  12. const int N=3e6+5,mod=1004535809;
  13. int M,lim=1,tim=0,pos[N],a[N],P,n,x,idx[N];
  14. inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
  15. inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
  16. inline int mul(int a,int b){return (ll)a*b%mod;}
  17. inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
  18. inline void ntt(int a[],int type){
  19. for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
  20. for(ri wn,mult=(mod-1)>>1,typ=type==1?3:334845270,mid=1;mid<lim;mid<<=1,mult>>=1){
  21. wn=ksm(typ,mult);
  22. for(ri j=0,len=mid<<1;j<lim;j+=len)for(ri w=1,k=0,a0,a1;k<mid;++k,w=mul(w,wn)){
  23. a0=a[j+k],a1=mul(w,a[j+k+mid]);
  24. a[j+k]=add(a0,a1),a[j+k+mid]=dec(a0,a1);
  25. }
  26. }
  27. if(type==-1)for(ri inv=ksm(lim,mod-2),i=0;i<lim;++i)a[i]=mul(a[i],inv);
  28. }
  29. inline void poly_mul(int a[],int b[]){
  30. static int A[N],B[N];
  31. for(ri i=0;i<lim;++i)A[i]=a[i],B[i]=b[i];
  32. ntt(A,1),ntt(B,1);
  33. for(ri i=0;i<lim;++i)A[i]=mul(A[i],B[i]);
  34. ntt(A,-1);
  35. for(ri i=0;i<lim;++i)a[i]=A[i];
  36. for(ri i=lim-1;i>=M-1;--i)a[i-M+1]=add(a[i-M+1],a[i]),a[i]=0;
  37. }
  38. inline void solve(int a[],int p){
  39. static int ret[N];
  40. memset(ret,0,sizeof(ret)),ret[0]=1;
  41. for(;p;p>>=1,poly_mul(a,a))if(p&1)poly_mul(ret,a);
  42. cout<<ret[x];
  43. }
  44. inline bool check(int g){
  45. for(ri i=0;i<M;++i)idx[i]=-1;
  46. for(ri i=0,mul=1;i<M-1;++i,mul=mul*g%M){
  47. if(~idx[mul])return 0;
  48. idx[mul]=i;
  49. }
  50. return 1;
  51. }
  52. inline void init(){
  53. while(lim<=M*2)lim<<=1,++tim;
  54. for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
  55. for(ri g=1;!check(g);++g);
  56. }
  57. int main(){
  58. P=read(),M=read(),init(),x=idx[read()],n=read();
  59. while(n--){
  60. int x=read();
  61. if(!x)continue;
  62. a[idx[x]]=1;
  63. }
  64. solve(a,P);
  65. return 0;
  66. }

2018.12.31 bzoj3992: [SDOI2015]序列统计(生成函数+ntt+快速幂)的更多相关文章

  1. LOJ 2183 / SDOI2015 序列统计 (DP+矩阵快速幂)

    题面 传送门 分析 考虑容斥原理,用总的方案数-不含质数的方案数 设\(dp1[i][j]\)表示前i个数,和取模p为j的方案数, \(dp2[i][j]\)表示前i个数,和取模p为j的方案数,且所有 ...

  2. [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1888  Solved: 898[Submit][Statu ...

  3. 【bzoj3992】[SDOI2015]序列统计 原根+NTT

    题目描述 求长度为 $n$ 的序列,每个数都是 $|S|$ 中的某一个,所有数的乘积模 $m$ 等于 $x$ 的序列数目模1004535809的值. 输入 一行,四个整数,N.M.x.|S|,其中|S ...

  4. BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)

    题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...

  5. BZOJ3992: [SDOI2015]序列统计

    Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...

  6. bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】

    还是没有理解透原根--题目提示其实挺明显的,M是质数,然后1<=x<=M-1 这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法 首先因为0和任何数乘都是0 ...

  7. BZOJ3992 [SDOI2015]序列统计 【生成函数 + 多项式快速幂】

    题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...

  8. 2018.12.31 bzoj4001: [TJOI2015]概率论(生成函数)

    传送门 生成函数好题. 题意简述:求nnn个点的树的叶子数期望值. 思路: 考虑fnf_nfn​表示nnn个节点的树的数量. 所以有递推式f0=1,fn=∑i=0n−1fifn−1−i(n>0) ...

  9. 【BZOJ3992】【SDOI2015】序列统计 EGF+多项式快速幂+循环卷积

    如果是求$n$个数之和在模$m$意义下为$x$,那么做法是显然的. 但是这道题问的是$n$个数之积在模m意义下为$x$,那么做法就和上面的问题不同. 考虑如何把乘法转换成加法(求log): 题目中有一 ...

随机推荐

  1. 如何彻底卸载mysql(xp)

    如何彻底卸载mysql 完整的卸载MySQL 5.x 的方法: 1.控制面板里的增加删除程序内进行删除 2.删除MySQL的安装文件夹C:\Program Files\MySQL,如果备份好,可以直接 ...

  2. java链接JDBC中的?问题

    String sql = "select * from student where name= ?"; PreparedStatement pst = conn.prepareSt ...

  3. 13-linux定时任务不起作用到的问题解决办法

    基本操作下面这篇: centos定时任务-不起作用- 没指明路径!!! 最大的问题是路径问题,以及权限问题. 用定时任务执行某些脚本是出现一系列问题,一步一步解决. 问题一:定时任务没反应: 查看日志 ...

  4. Linux下新建服务

    1 首先在/etc/rc.d/init.d/下添加脚本 asr_cron #!/bin/bash # $Id: rc.redhat.asterisk -- ::43Z tilghman $ # # a ...

  5. Jmeter常用脚本开发之Junit Request

    说明:Junit Request就是把Junit测试框架的自动化用例在jmeter上执行 步骤: 1.创建Java工程,编写Junit自动化测试用例 2.然后把用例打成jar包,复制到Jmter的li ...

  6. sharpsvn 继续,解决文件locked 问题,

    方法中少个方法就会出现一些问题. 比如进行了断线测试,结果再操作时就出现了文件被锁的情况,最终查了官网的论坛,才得以解决 How to unlock if the working copy is lo ...

  7. 8F - 采矿

    某天gameboy玩魔兽RPG.有一个任务是在一个富含金矿的圆形小岛上建一个基地,以最快的速度采集完这个小岛上的所有金矿.这个小岛上有n(0<n<1000000)个金矿,每个金矿的矿藏量是 ...

  8. Python知识

    1   注释 单行注释:#  内容 多行注释:A   """                   ''' 内容            或    内容 "&quo ...

  9. andorid 手机外部储存

    .xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ...

  10. UI设计初学者教程:色彩基础知识

    编辑:千锋UI设计 初学设计都会先认识三原色,通常我们说的三原色指的是颜料三原色:红.黄.蓝:其实三原色还有色光三原色:红.绿.蓝.我们通常说的红黄蓝就是减色法三原色,而红绿蓝是加色法三原色.可能这么 ...