【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中的所有元素。

Output

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

Sample Input

4 3 1 2
1 2

Sample Output

8

HINT

【样例说明】
可以生成的满足要求的不同的数列有(1,1,1,1)、(1,1,2,2)、(1,2,1,2)、(1,2,2,1)、(2,1,1,2)、(2,1,2,1)、(2,2,1,1)、(2,2,2,2)。
【数据规模和约定】
对于10%的数据,1<=N<=1000;
对于30%的数据,3<=M<=100;
对于60%的数据,3<=M<=800;
对于全部的数据,1<=N<=109,3<=M<=8000,M为质数,1<=x<=M-1,输入数据保证集合S中元素不重复

题解:如果你早已深入理解生成函数,可以无视下面这段话:

“未学生成函数的时候,以为这种题就是将两个桶相乘,得到一个新的桶,桶里装的是方案数。了解生成函数后,发现就是讲桶中的每一位都看成多项式中的一个系数,然后用多项式的运算法则来优化运算的过程,最后的答案依旧是其中的一位系数。如果像我一样对生成函数了解较少的话,可以先考虑DP,用DP方程将式子列出来,然后将整个DP数组看成一个大多项式,继续推下去就好。”

如果你早已深入理解NTT,可以无视下面这段话:

“NTT与FFT的区别是:FFT利用的是e的特性,将系数表达式与点值表达式进行快速的转换,而在NTT中,模数的原根正好有同样的性质,并且常见的就是998244353的一个原根=3。于是,只需要将单位复数根变成3的幂次,除法改成逆元,其余都一样了。”

如果你早已理解原根与指标,可以无视下面这段话:

“如果x^0,x^1,...x^n-1在mod n意义下正好覆盖了0-n-1中的所有数,则x是n的一个原根,他的意义可以看成是模意义下的e。而指标的意义,可以看成是模意义下的取ln。这两个东西在本题中的意义就是将乘法转变成加法。
“原根的求法:暴力枚举x,如果x对于$\varphi(p)$的所有质因子pi,都有$x^{\varphi(p) \over pi} \neq 1$,则x是p的原根。
“指标的求法:如果原根是r,则r^x的指标即为x。"

回到本题,我们将原数组求指标后,将得到的多项式^n即可,可以用多项式的快速幂实现。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. using namespace std;
  5. typedef long long ll;
  6. const ll P=1004535809ll;
  7. const ll G=3;
  8. const int maxn=100010;
  9. int n,m,X,S,root,num,len;
  10. ll pri[maxn],A[maxn],B[maxn];
  11. ll s[maxn],ind[maxn];
  12. inline int rd()
  13. {
  14. int ret=0,f=1; char gc=getchar();
  15. while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
  16. while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
  17. return ret*f;
  18. }
  19. ll pm(ll x,ll y,ll z)
  20. {
  21. ll ret=1;
  22. while(y)
  23. {
  24. if(y&1) ret=ret*x%z;
  25. x=x*x%z,y>>=1;
  26. }
  27. return ret;
  28. }
  29. void get_factor(ll x)
  30. {
  31. for(ll i=2;i*i<=x;i++)
  32. {
  33. if(x%i==0)
  34. {
  35. pri[++num]=i;
  36. while(x%i==0) x/=i;
  37. }
  38. }
  39. if(x!=1) pri[++num]=x;
  40. }
  41. bool check(ll x)
  42. {
  43. for(int i=1;i<=num;i++) if(pm(x,(m-1)/pri[i],m)==1) return 0;
  44. return 1;
  45. }
  46. ll get_root(ll x)
  47. {
  48. ll tmp=x-1;
  49. get_factor(tmp);
  50. for(ll i=2;i<=tmp;i++) if(check(i)) return i;
  51. return 0;
  52. }
  53. void NTT(ll *a,int f)
  54. {
  55. int i,j,k,h;
  56. ll t;
  57. for(i=k=0;i<len;i++)
  58. {
  59. if(i>k) swap(a[i],a[k]);
  60. for(j=len>>1;(k^=j)<j;j>>=1);
  61. }
  62. for(h=2;h<=len;h<<=1)
  63. {
  64. ll wn=pm(G,f==1?(P-1)/h:P-1-(P-1)/h,P);
  65. for(j=0;j<len;j+=h)
  66. {
  67. ll w=1;
  68. for(k=j;k<j+h/2;k++) t=w*a[k+h/2]%P,a[k+h/2]=(a[k]-t+P)%P,a[k]=(a[k]+t)%P,w=w*wn%P;
  69. }
  70. }
  71. if(f==-1)
  72. {
  73. t=pm(len,P-2,P);
  74. for(i=0;i<len;i++) a[i]=a[i]*t%P;
  75. }
  76. }
  77. void POW(ll *b,ll y)
  78. {
  79. ll *a=B;
  80. a[0]=1;
  81. while(y)
  82. {
  83. NTT(b,1);
  84. if(y&1)
  85. {
  86. NTT(a,1);
  87. for(int i=0;i<len;i++) a[i]=a[i]*b[i]%P;
  88. NTT(a,-1);
  89. for(int i=len-1;i>=m-1;i--) a[i-m+1]=(a[i-m+1]+a[i])%P,a[i]=0;
  90. }
  91. for(int i=0;i<len;i++) b[i]=b[i]*b[i]%P;
  92. NTT(b,-1);
  93. for(int i=len-1;i>=m-1;i--) b[i-m+1]=(b[i-m+1]+b[i])%P,b[i]=0;
  94. y>>=1;
  95. }
  96. }
  97. int main()
  98. {
  99. n=rd(),m=rd(),X=rd(),S=rd();
  100. int i;
  101. for(i=1;i<=S;i++) s[i]=rd();
  102. root=get_root(m);
  103. ll tmp=1;
  104. for(i=0;i<m-1;i++) ind[tmp]=i,tmp=tmp*root%m;
  105. for(len=1;len<=m+m;len<<=1);
  106. for(i=1;i<=S;i++) if(s[i]) A[ind[s[i]]]=1;
  107. POW(A,n);
  108. printf("%lld\n",B[ind[X]]);
  109. return 0;
  110. }

【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂的更多相关文章

  1. bzoj 3992 [SDOI2015] 序列统计 —— NTT (循环卷积+快速幂)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 (学习NTT:https://riteme.github.io/blog/2016-8 ...

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

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

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

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

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

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

  5. BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂

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

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

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

  7. 【NTT】bzoj3992: [SDOI2015]序列统计

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

  8. [SDOI2015]序列统计(NTT+求原根)

    题目 [SDOI2015]序列统计 挺好的题!!! 做法 \(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\) 显然是可以快速幂的:\[f[2*i][j]=\sum\limi ...

  9. BZOJ3992: [SDOI2015]序列统计

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

随机推荐

  1. LeetCode OJ-- Longest Common Prefix

    https://oj.leetcode.com/problems/longest-common-prefix/ 在多个string的集合中,找出所有string的最长公共前缀. 从头开始 index ...

  2. PHP中的stristr(),strstr(),strpos()速度比较

    测速代码: <?php function getmicrotime() { list($usec, $sec) = explode(" ",microtime()); ret ...

  3. Codeforces 546D Soldier and Number Game(数论)

    类似筛素数的方法……求出前缀和.然后直接O(1)回答即可. #include <bits/stdc++.h> using namespace std; #define rep(i,a,b) ...

  4. github如何实现fork的项目与原项目同步

    refer to https://www.jianshu.com/p/fede3333205f 作者:hitchc 链接:https://www.jianshu.com/p/fede3333205f ...

  5. GestureDetector 完全解析

    个人原创 OnDown(MotionEvent e):用户触发DonenEvent就会执行onShowPress(MotionEvent e):用户触发DonenEvent后,在很短大概0.5秒内,没 ...

  6. CSS 属性选择器的深入挖掘

    CSS 属性选择器,可以通过已经存在的属性名或属性值匹配元素. 属性选择器是在 CSS2 中引入的并且在 CSS3 中得到了很好拓展.本文将会比较全面的介绍属性选择器,尽可能的去挖掘这个选择器在不同场 ...

  7. 简单便捷的纯PHP网盘程序 Veno File Manager 2.6.3(VFM2)

    体验过很多国外网盘程序,例如:Owncloud.Bedrive.YetiShare.XFilesharing.uCloud.Cloudshare 等等,诸如此类,VFM2与这些臃肿的商用或非商用来的程 ...

  8. 优化算法——拟牛顿法之L-BFGS算法

    一.BFGS算法 在"优化算法--拟牛顿法之BFGS算法"中,我们得到了BFGS算法的校正公式: 利用Sherman-Morrison公式可对上式进行变换,得到 令,则得到: 二. ...

  9. ES聚合查询实例

    查询特定渠道分享数量最大的30个文章的uuid: { , "query": { "bool": { "must": [ { "te ...

  10. browsersync按照官网,然后本地配置后,动态监听时不起作用

    官方API也未曾标注,要添加文件指向 --files 所以解决方案就是: browser-sync start --proxy "tp5.cn" --files "css ...