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 ...
随机推荐
- Android studio 下的SDK Manager只显示已安装包的情况
原因是连接不上Google的更新服务器: 解决方法: 选择第三个Options: 修改Http Proxy Server: mirrors.neusoft.edu.cn Http Proxy Port ...
- Android为TV端助力 Service 两种启动方式的区别
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务.这两个方法都 可以启动Service,但是它们的使用场合有所不同.使 ...
- git 入门教程之版本控制
版本控制 我们知道 git 是分布式版本控制系统,所以称被控制对象是版本本身没错,但是从git 命令中发现,并没有版本这个名词,有的只是commit,所以前几节我一直称其为提交. 为了避免后续教程引发 ...
- 接口的绑定方案和动态SQL
1. 接口绑定方案 MyBatis中, 提供了一套接口绑定方案. 程序员可以提供一个接口, 然后提供对应接口的一个mapper.xml文件. MyBatis会自动将接口和xml文件进行绑定. 实际上就 ...
- LeetCode题解之Binary Tree Right Side View
1.题目描述 2.问题分析 使用层序遍历 3.代码 vector<int> v; vector<int> rightSideView(TreeNode* root) { if ...
- Windows Server 2012更新补丁后导致Micosoft ODBC for Oracle出现问题
上周由于WannaCry勒索病毒肆虐全球,14号系统管理员更新了一系列补丁后,导致一Windows Server 2012服务器上面部署的一些老旧的应用无法使用Microsoft ODBC for O ...
- 报错org.apache.hadoop.mapreduce.lib.input.FileSplit cannot be cast to org.apache.hadoop.mapred.FileSplit
报错 java.lang.Exception: java.lang.ClassCastException: org.apache.hadoop.mapreduce.lib.input.FileSpli ...
- spring4笔记----UrlResource访问网络资源读取xml内容
package com.ij34.bean; import java.util.Iterator; import java.util.List; import org.dom4j.Document; ...
- [20181122]模拟ORA-08103错误.txt
[20181122]模拟ORA-08103错误.txt $ oerr ora 810308103, 00000, "object no longer exists"// *Caus ...
- 自动化测试基础篇--Selenium判断元素是够存在
摘自https://www.cnblogs.com/sanzangTst/p/8376101.html selenium+python处于学习阶段,功能实现之后开始整理之前写的代码,突然发现一个功能没 ...