Luogu P3321 [SDOI2015]序列统计
一道不错的多项式好题。还涉及了一些数论内容。
首先我们看到题目是求乘积模\(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]序列统计的更多相关文章
- Luogu 3321 [SDOI2015]序列统计
BZOJ 3992 点开这道题之后才发现我对原根的理解大概只停留在$998244353$的原根是$3$…… 关于原根: 点我 首先写出$dp$方程,设$f_{i, j}$表示序列长度为$i$当前所有数 ...
- P3321 [SDOI2015]序列统计 FFT+快速幂+原根
\(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这 ...
- [洛谷P3321][SDOI2015]序列统计
题目大意:给你一个集合$n,m,x,S(S_i\in(0,m],m\leqslant 8000,m\in \rm{prime},n\leqslant10^9)$,求一个长度为$n$的序列$Q$,满足$ ...
- P3321 [SDOI2015]序列统计
思路 首先有个挺显然的DP \[ dp[i][(j*k)\%m]+=dp[i-1][j]\times dp[i-1][k] \] 想办法优化这个DP 这个dp也可以写成这样 \[ dp[i][j]=\ ...
- 洛咕 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)\)的 像我这 ...
- 洛谷P3321 [SDOI2015]序列统计(NTT)
传送门 题意:$a_i\in S$,求$\prod_{i=1}^na_i\equiv x\pmod{m}$的方案数 这题目太珂怕了……数学渣渣有点害怕……kelin大佬TQL 设$f[i][j]$表示 ...
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- [SDOI2015]序列统计
[SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...
- 3992: [SDOI2015]序列统计
3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...
随机推荐
- 杨学明老师推出全新课程--《敏捷开发&IPD和敏捷开发结合的实践》
课时:13小时(2天) 敏捷开发&IPD和敏捷开发结合的实践 讲 师:杨学明 [课程背景] 集成产品开发(IPD).集成能力成熟度模型(CMMI).敏捷开发(Agile Developmen ...
- Python 魔法方法简介
1.什么是魔法方法? 魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一 ...
- Python textwrap模块(文本包装和填充)
textwrap提供函数wrap().fill().indent().dedent()和以及TextWrapper类. 通常包装或者填充一两个字符串使用wrap()和fill().其他情况使用Text ...
- Keras深度学习框架安装及快速入门
1.下载安装Keras 如果你是安装的Anaconda组合套件,可以直接在Prompt上执行安装命令:pip install keras 注意:最下面为Successfully...表示安装成功! 2 ...
- mysql练习----The JOIN operation
game id mdate stadium team1 team2 1001 8 June 2012 National Stadium, Warsaw POL GRE 1002 8 June 2012 ...
- MyBatis笔记----多表关联查询两种方式实现
数据库 方式一:XML 按照下面类型建立article表 Article.java package com.ij34.model; public class Article { private int ...
- define和typedef的区别
define和typedef的区别 define是单纯的字符替换,typedef是重新定义了新的类型 #include <stdio.h> #define CHAR1 char* type ...
- VS2017做为Unity3D的脚本编辑器需要的最精简组件
前言 使用VS2017做为Unity的脚本编辑器,需要的最精简组件. 我的测试环境 windows 10 x64 windows 7 x64 sp1 时间:2017-4-22 更新于2018-12-4 ...
- [Hive_5] Hive 的 JDBC 编程
0. 说明 Hive 的 JDBC 编程 1. hiveserver2 介绍 hiveserver2 是 Hive 的 JDBC 接口,用户可以连接此端口来连接 Hive 服务器 JDBC 驱动类为 ...
- 适合使用并行的一种bfs
这种写法的bfs和前面的最大区别在于它对队列的处理,之前的简单bfs是每次从队列中取出当前的访问节点后,之后就将它的邻接节点加入到队列中,这样明显不利于并行化, 为此,这里使用了两个队列,第一个队列上 ...