一道不错的多项式好题。还涉及了一些数论内容。

首先我们看到题目是求乘积模\(m\)的方案数,考虑到这种方案数我们一般都可以用生成函数来做。

但显然卷积的下标有加(FFT,NTT等)有位运算(FWT)但是没有乘法的。除非您十分dalao自己发明一个卷积算法

所以我们考虑化乘为加,我们注意到\(m\)是一个不大的指数,那么意味这我们可以利用同余系下的一大利器——原根

关于原根的主要性质,其实就是原根\(g\),满足\(g^0,g^1\dots g^{m-2}\)模\(m\)后各不相同。

所以我们可以暴力找出原根(可以参考dalao's blog),然后把每一个数转化为原根的幂指数

这样我们把两个数相乘时其实就是指数相加,那么直接多项式快速幂即可。

但是注意到这里的下标其实是在模意义下的,并且根据欧拉定理我们还可以知道指数模的是\(m-1\)(不是\(m\)!),这个我们在做完NTT时把跑到后面的项手动加到前面去就可以了。

复杂度\(O(m\log^2 n)\),实测跑得非常快。

CODE

#include<cstdio>
#define RI register int
using namespace std;
const int M=8005,mod=1004535809;
int n,m,tar,s,t,x,root,A[M<<2],rg[M],rst[M],cnt;
inline int quick_pow(int x,int r,int p=mod,int mul=1)
{
for (;r;r>>=1,x=1LL*x*x%p) if (r&1) mul=1LL*mul*x%p; return mul;
}
inline int get_root(int x)
{
RI i; for (i=2;i<=x-2;++i) if ((x-1)%i==0)
rg[++cnt]=i; for (i=2;;++i)
{
bool flag=1; for (RI j=1;j<=cnt;++j)
if (quick_pow(i,rg[j],x)==1) { flag=0; break; }
if (flag) return i;
}
}
inline void inc(int& x,int y)
{
if ((x+=y)>=mod) x-=mod;
}
inline void dec(int& x,int y)
{
if ((x-=y)<0) x+=mod;
}
class Poly_Solver
{
private:
int rev[M<<2],T[M<<2],lim,p;
inline void init(int n)
{
for (lim=1;lim<=n;lim<<=1,++p);
for (RI i=0;i<lim;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<p-1);
}
inline void swap(int& x,int& y)
{
int t=x; x=y; y=t;
}
inline void NTT(int *f,int opt)
{
RI i; for (i=0;i<lim;++i) if (i<rev[i]) swap(f[i],f[rev[i]]);
for (i=1;i<lim;i<<=1)
{
int m=i<<1,D=quick_pow(3,opt==1?(mod-1)/m:mod-1-(mod-1)/m);
for (RI j=0;j<lim;j+=m)
{
int W=1; for (RI k=0;k<i;++k,W=1LL*W*D%mod)
{
int x=f[j+k],y=1LL*f[i+j+k]*W%mod;
f[j+k]=f[i+j+k]=x; inc(f[j+k],y); dec(f[i+j+k],y);
}
}
}
if (opt==-1)
{
int Inv=quick_pow(lim,mod-2);
for (i=0;i<lim;++i) f[i]=1LL*f[i]*Inv%mod;
}
}
inline void mul_self(int *A)
{
RI i; for (NTT(A,1),i=0;i<lim;++i)
A[i]=1LL*A[i]*A[i]%mod;
NTT(A,-1); for (i=lim-1;i>=m-1;--i) inc(A[i-m+1],A[i]),A[i]=0;
}
inline void mul(int *A,int *B)
{
RI i; for (NTT(A,1),NTT(B,1),i=0;i<lim;++i) A[i]=1LL*A[i]*B[i]%mod;
NTT(A,-1); NTT(B,-1); for (i=lim-1;i>=m-1;--i) inc(A[i-m+1],A[i]),A[i]=0;
}
public:
inline int pow(int *A,int r,int tar)
{
for (init(m<<1),T[0]=1;r;r>>=1,mul_self(A))
if (r&1) mul(T,A); return T[tar];
}
}P;
int main()
{
RI i; scanf("%d%d%d%d",&n,&m,&tar,&s); root=get_root(m);
for (x=i=1;i<=m-2;++i) rst[x=1LL*x*root%m]=i;
for (i=1;i<=s;++i) scanf("%d",&x),x&&(A[rst[x]]=1);
return printf("%d\n",P.pow(A,n,rst[tar])),0;
}

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

  1. Luogu 3321 [SDOI2015]序列统计

    BZOJ 3992 点开这道题之后才发现我对原根的理解大概只停留在$998244353$的原根是$3$…… 关于原根: 点我 首先写出$dp$方程,设$f_{i, j}$表示序列长度为$i$当前所有数 ...

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

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

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

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

  4. P3321 [SDOI2015]序列统计

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

  5. 洛咕 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)\)的 像我这 ...

  6. 洛谷P3321 [SDOI2015]序列统计(NTT)

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

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

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

  8. [SDOI2015]序列统计

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

  9. 3992: [SDOI2015]序列统计

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

随机推荐

  1. Android项目实战(四十九):Andoird 7.0+相机适配

    解决方案类似: Android项目实战(四十):Andoird 7.0+ 安装APK适配 解决方法: 一.在AndroidManifest.xml 文件中添加 四大组件之一的 <provider ...

  2. 现有项目中集成Flutter

    本文列举了项目开发使用Flutter会遇到的问题,以及如何使用Flutter module在现有项目中集成Flutter,并对其原理进行了分析. 最近在做的一个商业项目,完全的使用Flutter编写的 ...

  3. CSS之精灵图(雪碧图)与字体图标

    本文内容: 精灵图 字体图标 首发日期:2018-05-01 精灵图: 在以前,每个图片资源都是独立的一张张图片,浏览器访问网站中的不同网页时是重复获取这一张张图片的,这代表需要访问很多次资源. 为了 ...

  4. SQL 中事务的分类

    先讲下事务执行流程: BEGIN和COMMIT PRINT @@TRANCOUNT --@@TRANCOUNT统计事务数量 BEGIN TRAN PRINT @@TRANCOUNT BEGIN TRA ...

  5. SQL Server死锁的解决过程

    某现场报一个SQL死锁,于是开启了1222跟踪: dbcc traceon(1222,-1) 一段时间之后拷贝ERROR文件查找相关信息,比较有用的摘录出来如下: 语句一: select study_ ...

  6. python中根据字符串导入模块module

    python中根据字符串导入模块module 需要导入importlib,使用其中的import_module方法 import importlib modname = 'datetime' date ...

  7. 深入学习SpringMVC以及学习总结

    一.优点: 1.SpringMVC简化web程序开发; 2.SpringMVC效率很好(单例模式): 3.SpringMVC提供了大量扩展点,方便程序员自定义功能: ①.DispatcherServl ...

  8. jvm结构

    JVM的基本结构及其各部分详解(一)  https://www.cnblogs.com/zwbg/p/6194470.html JVM的基本结构及其各部分详解(二) https://www.cnblo ...

  9. Leancloud+Valine打造Hexo个人博客极简评论系统

    以下配置是基于Next主题6.1.0版本 效果见个人博客的最下方评论. Leancloud配置 首先访问Leancloud官网https://leancloud.cn/ 有Github账号的小伙伴可以 ...

  10. puppet master 用 nginx + unicorn 作为前端

    目录 1. 概要 2. nginx + unicorn 配置 2.1. package 安装 2.2. 配置文件设置 2.2.1. 配置 unicorn 2.2.2. 配置nginx 2.3. 测试配 ...