显然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)\)的

像我这样的蒟蒻都能想到用类似快速幂一样的东西来转移是吧,那么就\(O(log_2 nm^2)\)了

非常难受,还是过不去

如果可以优化一下dp转移就好了,比如把乘改成加,就能用NTT了

然后就要用到一个叫做原根的东西,学NTT的时候只是记了一下不知道这货有啥用

质数\(m\)原根\(g\)的性质:对\(m-1\)进行唯一分解,\(m-1=p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}\),\(g\)对任何一个\(i\)都满足\(g^{\frac{m-1}{p_i}}\neq 1\)

然后,这个题要用到的就是,\(g^0,g^1,\cdots,g^{m-2}\)互不相同

那么,把原来f[1][i]变成f[1][g^{i-1}],就可以一一对应了,又把乘变成了加

#include<bits/stdc++.h>
#define il inline
#define vd void
#define int ll
#define mod 1004535809
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
il int Pow(int x,int y,int mo){
int ret=1;
while(y){
if(y&1)ret=ret*x%mo;
x=x*x%mo;y>>=1;
}
return ret;
}
const int G=3,iG=Pow(G,mod-2,mod);
int n,m,qx,k,F[8000];
struct yyb{
ll f[8000];
yyb(){memset(f,0,sizeof f);}
};
ll N,lg,rev[1<<14],P[1<<14],iP[1<<14],invN;
il vd ntt(ll*A,int n,int t){
for(int i=0;i<n;++i)if(rev[i]>i)std::swap(A[i],A[rev[i]]);
for(int o=1;o<n;o<<=1){
int W=t?P[o]:iP[o];
for(int*p=A;p!=A+n;p+=o<<1)
for(int i=0,w=1;i<o;++i,w=w*W%mod){
int t=w*p[i+o]%mod;
p[i+o]=(p[i]-t+mod)%mod;p[i]=(p[i]+t)%mod;
}
}
if(!t)for(int i=0;i<n;++i)A[i]=A[i]*invN%mod;
}
il yyb mul(const yyb&a,const yyb&b){
static int A[1<<14],B[1<<14];
memset(A,0,N*8),memset(B,0,N*8);
memcpy(A,a.f,sizeof a.f),memcpy(B,b.f,sizeof b.f);
ntt(A,N,1),ntt(B,N,1);
for(int i=0;i<N;++i)A[i]=A[i]*B[i]%mod;
ntt(A,N,0);
yyb ret;
for(int i=0;i<=m*2;++i)(ret.f[i%(m-1)]+=A[i])%=mod;
return ret;
}
signed main(){
n=gi(),m=gi(),qx=gi(),k=gi();
int gM;
{//get gM
int p[10],tot=0;
for(int x=m-1,i=2;i<=x;++i)
if(x%i==0){
p[++tot]=i;
while(x%i==0)x/=i;
}
for(int i=2;i<=m;++i){
for(int j=1;j<=tot;++j)if(Pow(i,(m-1)/p[j],m)==1)goto gg;
gM=i;break;gg:;
}
for(int i=0,j=1;i<m-1;++i,j=j*gM%m)F[j]=i;
}
N=1,lg=0;while(N<m<<1)N<<=1,++lg;
for(int i=0;i<N;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<lg-1);
for(int i=1;i<N;i<<=1)P[i]=Pow(G,(mod-1)/(i<<1),mod),iP[i]=Pow(iG,(mod-1)/(i<<1),mod);
invN=Pow(N,mod-2,mod);
yyb X,ans;
int t;
while(k--){
t=gi();
if(t)X.f[F[t]]=1;
}
ans.f[F[1]]=1;
while(n){
if(n&1)ans=mul(ans,X);
X=mul(X,X);n>>=1;
}
printf("%lld\n",ans.f[F[qx]]);
return 0;
}

洛咕 P3321 [SDOI2015]序列统计的更多相关文章

  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]序列统计(NTT)

    传送门 题意:$a_i\in S$,求$\prod_{i=1}^na_i\equiv x\pmod{m}$的方案数 这题目太珂怕了……数学渣渣有点害怕……kelin大佬TQL 设$f[i][j]$表示 ...

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

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

  4. P3321 [SDOI2015]序列统计

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

  5. Luogu P3321 [SDOI2015]序列统计

    一道不错的多项式好题.还涉及了一些数论内容. 首先我们看到题目是求乘积模\(m\)的方案数,考虑到这种方案数我们一般都可以用生成函数来做. 但显然卷积的下标有加(FFT,NTT等)有位运算(FWT)但 ...

  6. 洛谷3321 SDOI2015 序列统计

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

  7. 【LG3321】[SDOI2015]序列统计

    [LG3321][SDOI2015]序列统计 题面 洛谷 题解 前置芝士:原根 我们先看一下对于一个数\(p\),它的原根\(g\)有什么性质(好像就是定义): \(g^0\%p,g^1\%p,g^2 ...

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

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

  9. [SDOI2015]序列统计

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

随机推荐

  1. Imagex用法

    imagex用来合并/导出wim映像实例 查看wim中包含的所有单个wim实例信息,注意其中的index是唯一的,用来区分不同的wim,导出的时候也通过该index导出相应的wimimagex /in ...

  2. Mosquitto安装调试实录

    1. 安装 以Centos 7.x为例,先安装依赖项(笔者使用阿里云资源,部分依赖项可能未列出): yum install gcc-c++ yum install openssl-devel yum ...

  3. 最小生成数 克鲁斯卡尔 普里姆 matlab

    克鲁斯卡尔: function T=MST_Kruskal(G) n=0; if isfield(G,'w') && ~isempty(G.w) && size(G.w ...

  4. September 16th 2017 Week 37th Saturday

    We are all in the gutter, but some of us are looking at the stars. 身处艰难,但仍有人仰望星空. When standing on t ...

  5. ZT 查找字符串中连续最长的数字串

    查找字符串中连续最长的数字串 有俩方法,1)比较好理解一些.2)晦涩 1) /* 功能:在字符串中找出连续最长的数字串,并把这个串的长度返回, 并把这个最长数字串付给其中一个函数参数outputstr ...

  6. .split("\n") 和 .strip("我是诗人的感叹")

    s10='''诗人 学者 作家 # 这里面是有换行     "\n"    的,    要想变成一行, 删除strip不行,要用 split分开,这样就能变成一个列表,里面是各个字 ...

  7. 个人技术博客(1/2)android布局技巧

    (1)weight属性的合理应用 当使用match_parent(fill_parent)时,需要经过计算,否则会出现如下情况 代码: <LinearLayout xmlns:android=& ...

  8. iis7.5加fck解析漏洞后台拿shell

    记录下来 经常用到 电脑准备格式化了 一切从头开始 每天浑浑噩噩的不知道干什么.认准一样东西 认认真真的学 IIS6.0解析漏洞,可以上传a.asp;.jps或者a.asp;a.jpg或者a.asp目 ...

  9. php实现简单的单链表

    <?php /** * 建立一个链表,节点的data为数组,记录一个id,完成链表所以操作 */ //结点,结点数据data定义为一个数组,id和value class Node{ public ...

  10. VMWare虚拟机下为Ubuntu 12.04.1配置静态IP(NAT方式)

    背景 在虚拟机下运行操作系统,尤其是Linux系统已经是非常常见的做法.有时你想在虚拟机下搭建一个(模拟)服务器来供主机访问,比如搭建一个telnet/ssh.此时你会发现,每次启动虚拟机,VMWar ...