题目描述

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

题解

先考虑一个dp,就是设dp[i][j]表示已经构造好了前i个元素,它们的乘积为j的方案数。

转移:dp[i][j]=dp[i-1][k]*f[j/k] 

看起来很像是卷积然鹅不是,他们中间是乘法关系而不是加法。

这时我们考虑一个限制,就是m是一个质数。

它有什么好处,就是当x,y互质时,那么x1x2....xy-1会遍历0-y-1的所有数。、

这样我们可以把1-m-1代换一下。

dp[i][j]=dp[i-1][k]*f[l] (gkgl=gj)

因为存在一一对应的关系,所以我们就可以代换了。

然后就变成了卷积的形式,多项式快速幂解决,因为每层的转移都是一样的。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define N 32002
  5. using namespace std;
  6. typedef long long ll;
  7. const int mod=;
  8. const int G=;
  9. const int Gi=;
  10. ll l,ny2,x,rev[N],L,n,m,a[N],b[N],s,g,c[N],tran[N],f[N];
  11. inline int rd(){
  12. int x=;char c=getchar();bool f=;
  13. while(!isdigit(c)){if(c=='-')f=;c=getchar();}
  14. while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
  15. return f?-x:x;
  16. }
  17. inline ll power(ll x,ll y){
  18. ll ans=;
  19. while(y){if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;}
  20. return ans;
  21. }
  22. inline void NTT(ll *a,int tag){
  23. for(int i=;i<l;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
  24. for(int i=;i<l;i<<=){
  25. ll wn=power(tag==?G:Gi,(mod-)/(i<<));
  26. for(int j=;j<l;j+=(i<<)){
  27. ll w=;
  28. for(int k=;k<i;++k,w=w*wn%mod){
  29. int x=a[j+k],y=a[i+j+k]*w%mod;
  30. a[j+k]=(x+y)%mod;a[i+j+k]=(x-y+mod)%mod;
  31. }
  32. }
  33. }
  34. }
  35. inline void ch(ll a[],ll *b){
  36. memcpy(c,a,sizeof(c));
  37. NTT(c,);NTT(b,);
  38. for(int i=;i<l;++i)b[i]=b[i]*c[i]%mod;
  39. NTT(b,-);
  40. for(int i=;i<l;++i)b[i]=b[i]*ny2%mod;
  41. for(int i=m;i<(m<<);++i)(b[i-m]+=b[i])%=mod,b[i]=;
  42. }
  43. inline ll ksm(ll x,ll y,ll m){
  44. ll ans=;
  45. while(y){if(y&)ans=ans*x%m;x=x*x%m;y>>=;}
  46. return ans;
  47. }
  48. inline int get_g(int m){
  49. for(int i=;i<=m-;++i)if((m-)%i==)f[++f[]]=i;
  50. for(int i=;;++i){
  51. bool x=;
  52. for(int j=;j<=f[]&&x;++j)if(ksm(i,f[j],m)==)x=;
  53. if(x)return i;
  54. }
  55. }
  56. int main(){
  57. n=rd();m=rd();x=rd();s=rd();
  58. g=get_g(m);
  59. for(ll i=,k=;i<m-;++i,k=k*g%m)tran[k]=i;
  60. m--;
  61. l=;L=;
  62. while(l<(m<<))l<<=,L++;int y;
  63. ny2=power(l,mod-);
  64. for(int i=;i<l;++i)rev[i]=(rev[i>>]>>)|((i&)<<(L-));
  65. for(int i=;i<=s;++i){
  66. y=rd();
  67. if(y)a[tran[y]]=;
  68. }
  69. b[tran[]]=;
  70. while(n){
  71. if(n&)ch(a,b);
  72. ch(a,a);n>>=;
  73. }
  74. cout<<b[tran[x]];
  75. return ;
  76. }

原根的求法:

暴力枚举,然后枚举m-1的所有质因子,若i^p==1则不是原根。

  1. inline int get_g(int m){
  2. for(int i=;i<=m-;++i)if((m-)%i==)f[++f[]]=i;
  3. for(int i=;;++i){
  4. bool x=;
  5. for(int j=;j<=f[]&&x;++j)if(ksm(i,f[j],m)==)x=;
  6. if(x)return i;
  7. }
  8. }

[SDOI2015]序列统计(多项式快速幂)的更多相关文章

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

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

  2. P3321 [SDOI2015]序列统计 FFT+快速幂+原根

    \(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这 ...

  3. 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

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

  4. BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)

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

  5. BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]

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

  6. 【洛谷3321_BZOJ3992】[SDOI2015]序列统计(原根_多项式)

    题目: 洛谷3321 分析: 一个转化思路比较神(典型?)的题-- 一个比较显然的\(O(n^3)\)暴力是用\(f[i][j]\)表示选了\(i\)个数,当前积在模\(m\)意义下为\(j\)的方案 ...

  7. 3992: [SDOI2015]序列统计

    3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...

  8. 【题解】SDOI2015序列统计

    [题解]SDOI2015序列统计 来自永不AFO的YYB的推荐 这里是乘积,比较麻烦,不过由于给定的序列膜数是个小质数,所以可以\(O(m^2\log m)\)找原跟(实际上不需要这么多). 乘积有点 ...

  9. [SDOI2015]序列统计

    [SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...

随机推荐

  1. # 【Python3练习题 004】输入某年某月某日,判断这一天是这一年的第几天?

    # [Python练习题 004]输入某年某月某日,判断这一天是这一年的第几天? # 思路:先判断是否为闰年,这关系到 2 月份的天数.# 之后再根据月份值把前几个月的天数累积加起来,最后再加上个“日 ...

  2. php单元测试

    https://blog.csdn.net/gaisidewangzhan1/article/details/80347008

  3. C# Note15:设置Window图标的正确方式

    Windows Presentation Foundation(WPF)独立应用程序有两种类型的图标: 一个程序集(assembly) 图标,通过在应用程序的项目构建文件中使用<Applicat ...

  4. Linux安装mysql5.6

    安装mysql5.6https://www.cnblogs.com/wangdaijun/p/6132632.html

  5. Mybaits整合Spring

    整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mapper代理形 ...

  6. Visual Studio 2017调试开源项目代码

    在我们的开发过程中很多时候我们会从GitHub上面下载一些开源的项目代码,然后在此基础上进行调试,正常情况下我们只需要将项目的源代码编译成Dll或者在.Net Core项目中直接引用相应的Nuget包 ...

  7. TensorFlow总结

    第一 基础 1. 定义变量 #定义维度为[2,3], 平均值为·1, 标准差为1,类型为float32,名称为w1的服从正态分布的变量 w1 = tf.Variable(tf.random_norma ...

  8. AngularJS从入门到精通

    第一 AngularJS的四大特性 1. MVC 例如:使用angularjs向模板传递数据 <!doctype html> <html> <head> <m ...

  9. 解析$(this).data('type');

    html: <button type="button" class="layui-btn layui-btn-sm" data-type="ad ...

  10. How to reset macOS Icon Cache

    find . -name cuthead.txt find /private/var/folders/ -name 'com.apple.dock.iconcache' -delete find /p ...