2018.12.31 bzoj3992: [SDOI2015]序列统计(生成函数+ntt+快速幂)
传送门
生成函数简单题。
题意:给出一个集合A={a1,a2,...as}A=\{a_1,a_2,...a_s\}A={a1,a2,...as},所有数都在[0,m−1][0,m-1][0,m−1]之间,mmm是一个质数,求满足全部由这个集合里的组成且长度为nnn且所有数之积与xxx在模mmm意义下相同的数列总数。
思路:对a1,a2,..,as,xa_1,a_2,..,a_s,xa1,a2,..,as,x全部化成gb1,gb2,...gbs,gyg^{b_1},g^{b_2},...g^{b_s},g^{y}gb1,gb2,...gbs,gy,然后就转乘法为加法。
于是只用求x1+x2+...+xn≡ymod  m−1x_1+x_2+...+x_n\equiv y\mod m-1x1+x2+...+xn≡ymodm−1,其中xi∈{b1,b2,...bs}x_i\in\{b_1,b_2,...b_s\}xi∈{b1,b2,...bs}的方案数。
对于xix_ixi可以构造出生成函数1+xb1+xb2+...+xbs1+x^{b_1}+x^{b_2}+...+x^{b_s}1+xb1+xb2+...+xbs,于是答案的生成函数就是(1+xb1+xb2+...+xbs)n(1+x^{b_1}+x^{b_2}+...+x^{b_s})^n(1+xb1+xb2+...+xbs)n,考虑到nnn很大可以用快速幂+nttnttntt解决。
注意特判ai=0a_i=0ai=0的情况以及每次nttnttntt完了之后要重新把多项式的最高次数控制为m−2m-2m−2
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
const int N=3e6+5,mod=1004535809;
int M,lim=1,tim=0,pos[N],a[N],P,n,x,idx[N];
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
inline void ntt(int a[],int type){
for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
for(ri wn,mult=(mod-1)>>1,typ=type==1?3:334845270,mid=1;mid<lim;mid<<=1,mult>>=1){
wn=ksm(typ,mult);
for(ri j=0,len=mid<<1;j<lim;j+=len)for(ri w=1,k=0,a0,a1;k<mid;++k,w=mul(w,wn)){
a0=a[j+k],a1=mul(w,a[j+k+mid]);
a[j+k]=add(a0,a1),a[j+k+mid]=dec(a0,a1);
}
}
if(type==-1)for(ri inv=ksm(lim,mod-2),i=0;i<lim;++i)a[i]=mul(a[i],inv);
}
inline void poly_mul(int a[],int b[]){
static int A[N],B[N];
for(ri i=0;i<lim;++i)A[i]=a[i],B[i]=b[i];
ntt(A,1),ntt(B,1);
for(ri i=0;i<lim;++i)A[i]=mul(A[i],B[i]);
ntt(A,-1);
for(ri i=0;i<lim;++i)a[i]=A[i];
for(ri i=lim-1;i>=M-1;--i)a[i-M+1]=add(a[i-M+1],a[i]),a[i]=0;
}
inline void solve(int a[],int p){
static int ret[N];
memset(ret,0,sizeof(ret)),ret[0]=1;
for(;p;p>>=1,poly_mul(a,a))if(p&1)poly_mul(ret,a);
cout<<ret[x];
}
inline bool check(int g){
for(ri i=0;i<M;++i)idx[i]=-1;
for(ri i=0,mul=1;i<M-1;++i,mul=mul*g%M){
if(~idx[mul])return 0;
idx[mul]=i;
}
return 1;
}
inline void init(){
while(lim<=M*2)lim<<=1,++tim;
for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
for(ri g=1;!check(g);++g);
}
int main(){
P=read(),M=read(),init(),x=idx[read()],n=read();
while(n--){
int x=read();
if(!x)continue;
a[idx[x]]=1;
}
solve(a,P);
return 0;
}
2018.12.31 bzoj3992: [SDOI2015]序列统计(生成函数+ntt+快速幂)的更多相关文章
- LOJ 2183 / SDOI2015 序列统计 (DP+矩阵快速幂)
题面 传送门 分析 考虑容斥原理,用总的方案数-不含质数的方案数 设\(dp1[i][j]\)表示前i个数,和取模p为j的方案数, \(dp2[i][j]\)表示前i个数,和取模p为j的方案数,且所有 ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- 【bzoj3992】[SDOI2015]序列统计 原根+NTT
题目描述 求长度为 $n$ 的序列,每个数都是 $|S|$ 中的某一个,所有数的乘积模 $m$ 等于 $x$ 的序列数目模1004535809的值. 输入 一行,四个整数,N.M.x.|S|,其中|S ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- BZOJ3992: [SDOI2015]序列统计
Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...
- bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】
还是没有理解透原根--题目提示其实挺明显的,M是质数,然后1<=x<=M-1 这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法 首先因为0和任何数乘都是0 ...
- BZOJ3992 [SDOI2015]序列统计 【生成函数 + 多项式快速幂】
题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...
- 2018.12.31 bzoj4001: [TJOI2015]概率论(生成函数)
传送门 生成函数好题. 题意简述:求nnn个点的树的叶子数期望值. 思路: 考虑fnf_nfn表示nnn个节点的树的数量. 所以有递推式f0=1,fn=∑i=0n−1fifn−1−i(n>0) ...
- 【BZOJ3992】【SDOI2015】序列统计 EGF+多项式快速幂+循环卷积
如果是求$n$个数之和在模$m$意义下为$x$,那么做法是显然的. 但是这道题问的是$n$个数之积在模m意义下为$x$,那么做法就和上面的问题不同. 考虑如何把乘法转换成加法(求log): 题目中有一 ...
随机推荐
- TOJ4127: Root of String
传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4127 4127: Root of ...
- 164. Maximum Gap (Array; sort)
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- 200. Number of Islands (Graph)
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...
- unity填色绘画游戏Drawing Coloring Extra Edition
. 下载地址: https://item.taobao.com/item.htm?spm=0.7095261.0.0.2e611debLdF3mf&id=576153069662
- 转移动APP测试实践
http://blog.csdn.net/hgstclyh/article/details/53115325
- linux同步机制
很早之前就接触过同步这个概念了,但是一直都很模糊,没有深入地学习了解过,近期有时间了,就花时间研习了一下<linux内核标准教程>和<深入linux设备驱动程序内核机制>这两本 ...
- Anaconda常用命令大全
使用conda 首先我们将要确认你已经安装好了conda 配置环境 下一步我们将通过创建几个环境来展示conda的环境管理功能.使你更加轻松的了解关于环境的一切.我们将学习如何确认你在哪个环境中,以及 ...
- Quartz代码及配置详解(转)
Quartz可以用来做什么? Quartz是一个任务调度框架.比如你遇到这样的问题 想每月25号,信用卡自动还款 想每年4月1日自己给当年暗恋女神发一封匿名贺卡 想每隔1小时,备份一下自己的爱情动作片 ...
- go语言中的并发
package main; import ( "fmt" "runtime" "sync" ) //goruntine奉行通过通信来共享内存 ...
- 同一台主机部署两个比特币钱包以及rpc服务的摘要
.bitcoin QA Test环境 启动指定参数: "C:\Program Files (x86)\Bitcoin\bitcoin-qt.exe" -testnet -serve ...