【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂
【BZOJ3992】[SDOI2015]序列统计
Description
Input
一行,四个整数,N、M、x、|S|,其中|S|为集合S中元素个数。第二行,|S|个整数,表示集合S中的所有元素。
Output
一行,一个整数,表示你求出的种类数mod 1004535809的值。
Sample Input
1 2
Sample Output
HINT
题解:如果你早已深入理解生成函数,可以无视下面这段话:
“未学生成函数的时候,以为这种题就是将两个桶相乘,得到一个新的桶,桶里装的是方案数。了解生成函数后,发现就是讲桶中的每一位都看成多项式中的一个系数,然后用多项式的运算法则来优化运算的过程,最后的答案依旧是其中的一位系数。如果像我一样对生成函数了解较少的话,可以先考虑DP,用DP方程将式子列出来,然后将整个DP数组看成一个大多项式,继续推下去就好。”
如果你早已深入理解NTT,可以无视下面这段话:
“NTT与FFT的区别是:FFT利用的是e的特性,将系数表达式与点值表达式进行快速的转换,而在NTT中,模数的原根正好有同样的性质,并且常见的就是998244353的一个原根=3。于是,只需要将单位复数根变成3的幂次,除法改成逆元,其余都一样了。”
如果你早已理解原根与指标,可以无视下面这段话:
“如果x^0,x^1,...x^n-1在mod n意义下正好覆盖了0-n-1中的所有数,则x是n的一个原根,他的意义可以看成是模意义下的e。而指标的意义,可以看成是模意义下的取ln。这两个东西在本题中的意义就是将乘法转变成加法。
“原根的求法:暴力枚举x,如果x对于$\varphi(p)$的所有质因子pi,都有$x^{\varphi(p) \over pi} \neq 1$,则x是p的原根。
“指标的求法:如果原根是r,则r^x的指标即为x。"
回到本题,我们将原数组求指标后,将得到的多项式^n即可,可以用多项式的快速幂实现。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll P=1004535809ll;
const ll G=3;
const int maxn=100010;
int n,m,X,S,root,num,len;
ll pri[maxn],A[maxn],B[maxn];
ll s[maxn],ind[maxn];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
ll pm(ll x,ll y,ll z)
{
ll ret=1;
while(y)
{
if(y&1) ret=ret*x%z;
x=x*x%z,y>>=1;
}
return ret;
}
void get_factor(ll x)
{
for(ll i=2;i*i<=x;i++)
{
if(x%i==0)
{
pri[++num]=i;
while(x%i==0) x/=i;
}
}
if(x!=1) pri[++num]=x;
}
bool check(ll x)
{
for(int i=1;i<=num;i++) if(pm(x,(m-1)/pri[i],m)==1) return 0;
return 1;
}
ll get_root(ll x)
{
ll tmp=x-1;
get_factor(tmp);
for(ll i=2;i<=tmp;i++) if(check(i)) return i;
return 0;
}
void NTT(ll *a,int f)
{
int i,j,k,h;
ll t;
for(i=k=0;i<len;i++)
{
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(h=2;h<=len;h<<=1)
{
ll wn=pm(G,f==1?(P-1)/h:P-1-(P-1)/h,P);
for(j=0;j<len;j+=h)
{
ll w=1;
for(k=j;k<j+h/2;k++) t=w*a[k+h/2]%P,a[k+h/2]=(a[k]-t+P)%P,a[k]=(a[k]+t)%P,w=w*wn%P;
}
}
if(f==-1)
{
t=pm(len,P-2,P);
for(i=0;i<len;i++) a[i]=a[i]*t%P;
}
}
void POW(ll *b,ll y)
{
ll *a=B;
a[0]=1;
while(y)
{
NTT(b,1);
if(y&1)
{
NTT(a,1);
for(int i=0;i<len;i++) a[i]=a[i]*b[i]%P;
NTT(a,-1);
for(int i=len-1;i>=m-1;i--) a[i-m+1]=(a[i-m+1]+a[i])%P,a[i]=0;
}
for(int i=0;i<len;i++) b[i]=b[i]*b[i]%P;
NTT(b,-1);
for(int i=len-1;i>=m-1;i--) b[i-m+1]=(b[i-m+1]+b[i])%P,b[i]=0;
y>>=1;
}
}
int main()
{
n=rd(),m=rd(),X=rd(),S=rd();
int i;
for(i=1;i<=S;i++) s[i]=rd();
root=get_root(m);
ll tmp=1;
for(i=0;i<m-1;i++) ind[tmp]=i,tmp=tmp*root%m;
for(len=1;len<=m+m;len<<=1);
for(i=1;i<=S;i++) if(s[i]) A[ind[s[i]]]=1;
POW(A,n);
printf("%lld\n",B[ind[X]]);
return 0;
}
【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂的更多相关文章
- bzoj 3992 [SDOI2015] 序列统计 —— NTT (循环卷积+快速幂)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 (学习NTT:https://riteme.github.io/blog/2016-8 ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- LOJ 2183 / SDOI2015 序列统计 (DP+矩阵快速幂)
题面 传送门 分析 考虑容斥原理,用总的方案数-不含质数的方案数 设\(dp1[i][j]\)表示前i个数,和取模p为j的方案数, \(dp2[i][j]\)表示前i个数,和取模p为j的方案数,且所有 ...
- 【BZOJ3992】【SDOI2015】序列统计 EGF+多项式快速幂+循环卷积
如果是求$n$个数之和在模$m$意义下为$x$,那么做法是显然的. 但是这道题问的是$n$个数之积在模m意义下为$x$,那么做法就和上面的问题不同. 考虑如何把乘法转换成加法(求log): 题目中有一 ...
- BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1155 Solved: 532[Submit][Statu ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- 【NTT】bzoj3992: [SDOI2015]序列统计
板子题都差点不会了 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生 ...
- [SDOI2015]序列统计(NTT+求原根)
题目 [SDOI2015]序列统计 挺好的题!!! 做法 \(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\) 显然是可以快速幂的:\[f[2*i][j]=\sum\limi ...
- BZOJ3992: [SDOI2015]序列统计
Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...
随机推荐
- JavaScript变量提升和函数声明预解析
1.首先理解函数作用域 在JavaScript中,变量的定义并不是以代码块作为作用域的,而是以函数作用作用域的.也就是说,如果变量是在某个函数中定义的,那么它在函数以外的地方是不可见的.而如果该变量是 ...
- 链表ADT的实现
list.h文件 /*链表的类型声明*/ typedef int ElementType; /* START: fig3_6.txt */ #ifndef _List_H #define _List_ ...
- Android新特性之CardView的简单使用
Android新特性之CardView的简单使用 我们学习下Android5.0的新增加的控件CardView.首先我们了解一下CardView的基本使用,然后结合RecycleView使用CardV ...
- Codeforces Round #451 (Div. 2) A. Rounding【分类讨论/易错】
A. Rounding time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...
- httpd安装和配置(cgi、wsgi)
参考:http://webpy.org/cookbook/mod_wsgi-apache.zh-cn 一.yum方式安装: 1.yum install httpd 输入y后继续. 2.看到一下类似的返 ...
- 10.1综合强化刷题 Day4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
- 2016北京集训测试赛(十一)Problem C: 树链问题
Solution 智障暴力题, 每个点维护一下子树信息, 树剖就好了. 我居然还傻了写了一发毛毛虫... #include <cstdio> #include <cctype> ...
- 洛谷1373小a和uim之大逃离
题目背景 小a和uim来到雨林中探险.突然一阵北风吹来,一片乌云从北部天边急涌过来,还伴着一道道闪电,一阵阵雷声.刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个 ...
- MetaQ对接SparkStreaming示例代码
由于JavaReceiverInputDStream<String> lines = ssc.receiverStream(Receiver<T> receiver) 中 没有 ...
- 【音乐App】—— Vue-music 项目学习笔记:推荐页面开发
前言:以下内容均为学习慕课网高级实战课程的实践爬坑笔记. 上一篇总结了项目概述.项目准备.页面骨架搭建.这一篇重点梳理推荐页面开发.项目github地址:https://github.com/66We ...