传送门

题意:$a_i\in S$,求$\prod_{i=1}^na_i\equiv x\pmod{m}$的方案数

这题目太珂怕了……数学渣渣有点害怕……kelin大佬TQL

设$f[i][j]$表示$\prod_{k=1}^ia_k\equiv j\pmod{m}$的方案数

那么$$f[2*i][j]=\sum_{ab\equiv j\pmod{m}}f[i][a]f[i][b]$$

然后因为$m$是质数。质数有一个叫做原根的东西,质数$p$的原根$g$满足$g^i\ mod\ p$在$i$为$[1,p-1]$时互不相同,然后根据费马小定理$g^{p-1}\equiv 1\pmod{p}$,所以$i$在$[0,p-2]$的范围内$g^{i}$能取遍[1,p-1]的所有数(因为原根一般都特别小,所以可以直接暴力求,这个可以看代码)

因为$g^A\equiv a\pmod{m}$,每一个$A$和$a$互相对应,那么我们可以用$A$来代替$a$

则上式变为$$f[2*i][K]\equiv \sum_{g^Ag^B\equiv g^K\pmod{m}}f[i][A]f[i][B]$$

$$f[2*i][K]\equiv \sum_{g^{A+B}\equiv g^K\pmod{m}}f[i][A]f[i][B]$$

根据费马小定理$a^b\equiv a^{b\ mod\ p-1}\pmod{p}$,可得$$f[2*i][K]\equiv \sum_{g^{(A+B)\ mod\ m-1}=g^K}f[i][A]f[i][B]$$

$$f[2*i][K]\equiv \sum_{A+B\equiv K\pmod{m-1}}f[i][A]f[i][B]$$

设$g[K]=\sum_{A+B=K}f[i][A]f[i][B]$,则$$f[i*2][K]=g[K]+g[K+m-1]$$

然后这个每一层的转移都是一样的,所以用多项式快速幂来计算

 //minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define mul(x,y) (1ll*x*y%P)
#define add(x,y) (x+y>=P?x+y-P:x+y)
#define dec(x,y) (x-y<0?x-y+P:x-y)
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=,P=;
int n,m,vis[N],F[N],G[N],A[N],B[N],O[N];
int l,limit=,r[N],x,S,pr;
inline int ksm(int a,int b,int P){
int res=;a%=P;
while(b){
if(b&) res=mul(res,a);
a=mul(a,a),b>>=;
}
return res;
}
inline int calc(int x){
//求原根,若只有j=x-1时i^j=1(mod x),i是x的原根
if(x==) return ;
for(int i=;;++i){
bool flag=;
for(int j=;j*j<x;++j)
if(ksm(i,(x-)/j,x)==){flag=false;break;}
if(flag) return i;
}
}
void NTT(int *A,int type){
for(int i=;i<limit;++i)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=){
int R=mid<<,Wn=ksm(,(P-)/R,P);O[]=;
for(int j=;j<mid;++j) O[j]=mul(O[j-],Wn);
for(int j=;j<limit;j+=R){
for(int k=;k<mid;++k){
int x=A[j+k],y=mul(O[k],A[j+k+mid]);
A[j+k]=add(x,y),A[j+k+mid]=dec(x,y);
}
}
}
if(type==-){
reverse(A+,A+limit);
for(int i=,inv=ksm(limit,P-,P);i<limit;++i)
A[i]=mul(A[i],inv);
}
}
void Mul(int *G,int *F){
for(int i=;i<limit;++i) A[i]=G[i],B[i]=F[i];
NTT(A,),NTT(B,);
for(int i=;i<limit;++i) A[i]=mul(A[i],B[i]);
NTT(A,-);
for(int i=;i<m-;++i) G[i]=add(A[i],A[i+m-]); }
void solve(int b){
G[]=;
while(b){
if(b&) Mul(G,F);
b>>=,Mul(F,F);
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read(),x=read(),S=read();
pr=calc(m);
for(int i=,v;i<=S;++i)
vis[v=read()]=;
int pos=-;
for(int i=,j=;i<m-;++i,j=j*pr%m){
if(vis[j]) F[i]=;
if(j==x) pos=i;
}
if(pos==-) return puts(""),;
while(limit<=((m-)<<)) limit<<=,++l;
for(int i=;i<limit;++i)
r[i]=(r[i>>]>>)|((i&)<<(l-));
solve(n);
printf("%d\n",G[pos]%P);
return ;
}

洛谷P3321 [SDOI2015]序列统计(NTT)的更多相关文章

  1. [洛谷P3321][SDOI2015]序列统计

    题目大意:给你一个集合$n,m,x,S(S_i\in(0,m],m\leqslant 8000,m\in \rm{prime},n\leqslant10^9)$,求一个长度为$n$的序列$Q$,满足$ ...

  2. 洛咕 P3321 [SDOI2015]序列统计

    显然dp就是设\(f[i][j]\)表示dp了i轮,对m取膜是j的方案数 \(f[i][xy\mod m]=f[i-1][x]\times f[i-1][y]\) 这是\(O(nm^2)\)的 像我这 ...

  3. 洛谷3321 SDOI2015 序列统计

    懒得放传送[大雾 有趣的一道题 前几天刚好听到Creed_神犇讲到相乘转原根变成卷积的形式 看到这道题当然就会做了啊w 对于m很小 我们暴力找原根 如果你不会找原根的话 出门左转百度qwq 找到原根以 ...

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

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

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

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

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

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

  7. 【BZOJ】3992: [SDOI2015]序列统计 NTT+生成函数

    [题意]给定一个[0,m-1]范围内的数字集合S,从中选择n个数字(可重复)构成序列.给定x,求序列所有数字乘积%m后为x的序列方案数%1004535809.1<=n<=10^9,3< ...

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

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

  9. P3321 [SDOI2015]序列统计

    思路 首先有个挺显然的DP \[ dp[i][(j*k)\%m]+=dp[i-1][j]\times dp[i-1][k] \] 想办法优化这个DP 这个dp也可以写成这样 \[ dp[i][j]=\ ...

随机推荐

  1. Java类加载器( 死磕 6)

    [正文]Java类加载器(  CLassLoader )死磕 6:  自定义网络类加载器 本小节目录 6.1. 自定义网络类加载器的类设计 6.2. 文件传输Server端的源码 6.3. 文件传输C ...

  2. Sparksql 取代 Hive?

    sparksql  hive https://databricks.com/blog/2014/07/01/shark-spark-sql-hive-on-spark-and-the-future-o ...

  3. 代码空间项目 -- 获取当前时间之前的某一天-Calender类的使用

    Calendar类的静态方法getInstance()可以初始化一个日历对象:Calendar now = Calendar.getInstance(); 1.Calendar的基本用法calenda ...

  4. PAT天梯赛 L2-027. 名人堂与代金券 【排序】

    题目链接 https://www.patest.cn/contests/gplt/L2-027 思路 在输入的时候 判断分数 是否符合领取代金券条件 如果符合 SUM 就加上对应的代金券价值 然后在对 ...

  5. 对私有API提交的注意事项

    1.这个等于堵死了调试断点.关闭就不能断点调试了. 2.对于敏感的函数名要做一个对称加密处理. 防止二进制文件的静态扫描. 3.对于调用私有函数的方法,可以做一个宏定义包装. #define 你的正常 ...

  6. Docker的远程访问

    $docker : info (10.211.55是另一台服务器的地址) 频繁访问远程的docker服务器使用-H选项很麻烦,使用环境变量DOCKER_HOST, $export DOCKER_HOS ...

  7. egret+git+阿里云code搭建团队开发

    准备: GIT客户端 廖雪峰老师GIT教程 GIT客户端安装完成后,打开Git Bash ,输入代码 ,设置git提交与获取的git账户信息 git config --global user.name ...

  8. Memory Notification: Library Cache Object loaded into SGA

    问题现象: 数据库服务器可以ping通,但SSH连接不了:应用.plsqldeveloper 也都连接不了.事情到了这个地步,只能重启服务器. 服务器环境:oracle10.2.0.1 +rhel5. ...

  9. php字符串啊的heredoc格式

    Heredoc技术,在正规的PHP文档中和技术书籍中一般没有详细讲述,只是提到了这是一种Perl风格的字符串输出技术.它也出现unix/linux的shell编程里面.但是现在的一些论坛程序,和部分文 ...

  10. 大数相乘(hdu 1402)

    ------------------题目链接--------------------- 题目没啥说的,两个数相乘,fft,一发模板就AC,kuangbin模板大法好,不懂原理的小白也能体验AC. 个人 ...