【题解】SDOI2015序列统计

来自永不AFO的YYB的推荐

这里是乘积,比较麻烦,不过由于给定的序列膜数是个小质数,所以可以\(O(m^2\log m)\)找原跟(实际上不需要这么多)。

乘积有点麻烦,转换成加法就好了,然后取离散对数\(a_i\equiv g^{c_i} \mod m\),现在每个元素都用原根的指数代替了,问题就转变成了有多少种方案使得每个元素的乘积等于\(\log x\mod m\)。

根据题意直接构造

\[F(x)=\sum [\exist \log a_i=i]x^i
\]

答案就是

\[F(x)^n
\]

吗?

其实要魔改一下,乘的过程中要不断地让\(F(x)\)大于\(x^m\)的系数算到\(x^{i \mod m}\)上,原因显然,略。

不能这么敷衍,到时候自己看会一头雾水,取膜的原因是,我们利用的是多项式乘法的组合意义,现在组合意义是要得到\(c_i=\sum_\limits{k+j \equiv i \mod m}a_kb_j\),所以如此。

既然要不断地让\(F(x)\)对\(x^m\)取膜,所以\(\ln ,\exp\)废了

直接写两个\(\log\)快速幂跑得飞快

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector> using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
} int n,m,x,s,g;
vector < int > ve;
const int maxn=8009;
int lg[maxn];
int read[1<<19|1];
int ans[1<<19|1]; namespace poly{
const int maxn=1<<19|1;
int a[maxn],b[maxn],r[maxn];
int savlen;
inline void getr(const int&len){
if(len==savlen)return;
int cnt=0;
for(register int t=1;t<len;t<<=1)++cnt;
for(register int t=1;t<len;++t)
r[t]=r[t>>1]>>1|(t&1)<<cnt>>1;
}
const int mod=1004535809;
const int g=3;
inline int ksm(int base,ll p){
register int ret=1;
for(base%=mod;p;p>>=1,base=1ll*base*base%mod)
if(p&1) ret=1ll*ret*base%mod;
return ret;
}
const int gi=ksm(3,mod-2); inline void NTT(int*a,const int&len,const int&tag){
getr(len);
for(register int t=1;t<len;++t)
if(r[t]>t) swap(a[t],a[r[t]]);
int *a1,*a0,s=g;
if(tag!=1) s=gi;
for(register int t=1,wn;t<len;t<<=1){
wn=ksm(s,(mod-1)/(t<<1));
for(register int i=0;i<len;i+=t<<1){
a1=(a0=a+i)+t;
for(register int j=0,w=1,tm;j<t;++j,++a1,++a0,w=1ll*w*wn%mod){
tm=1ll**a1*w%mod;
*a1=(*a0-tm)%mod;
*a0=(*a0+tm)%mod;
if(*a1<0)*a1+=mod;
}
}
}
if(tag!=1)
for(register int t=0,in=ksm(len,mod-2);t<len;++t)
a[t]=1ll*a[t]*in%mod;
} inline void print(int*a,int len){
for(register int t=0;t<len;++t)
printf("%d ",a[t]);
putchar('\n');
} inline void KSM(int*a,int*b,const int&len,int p){
static int ret[maxn],base[maxn];
memset(ret,0,sizeof ret);
memset(base,0,sizeof base);
ret[0]=1;
for(register int t=0;t<len;++t) base[t]=a[t];
while(p){
NTT(base,len<<1,1);
if(p&1){
NTT(ret,len<<1,1);
for(register int t=0;t<len<<1;++t) ret[t]=1ll*ret[t]*base[t]%mod;
NTT(ret,len<<1,-1);
for(register int t=(len<<1)-1;t-m+1>=0;--t) ret[t-m+1]=(ret[t-m+1]+ret[t])%mod,ret[t]=0;
}
for(register int t=0;t<len<<1;++t) base[t]=1ll*base[t]*base[t]%mod;
NTT(base,len<<1,-1);
for(register int t=(len<<1)-1;t-m+1>=0;--t) base[t-m+1]=(base[t-m+1]+base[t])%mod,base[t]=0;
p>>=1;
}
for(int t=0;t<len;++t) b[t]=ret[t];
}
} inline int ksm(const int&base,const int&p,const int&mod=m){
register int ret=1;
for(register int t=p,b=base%mod;t;t>>=1,b=1ll*b*b%mod)
if(t&1) ret=1ll*ret*b%mod;
return ret;
} inline void findg(){
#define mod m
int k=m-1;
for(register int t=2;1ll*t*t<=k;++t){
if(k%t==0){
ve.push_back(t);
if(k/t!=t) ve.push_back(k/t);
}
}
//for(auto f:ve) cout<<"fac="<<f<<endl;
for(register int t=2;;++t){
int l=1;
for(auto f:ve)
if(ksm(t,f)==1) l=0;
if(l) {g=t;return;}
} #undef mod
} int main(){ freopen("sdoi2015_sequence.in","r",stdin);
freopen("sdoi2015_sequence.out","w",stdout); n=qr();m=qr();x=qr();s=qr();
findg(); for(register int t=1,k=g;t<m-1;++t,k=1ll*k*g%m) lg[k]=t;
for(register int t=1;t<=s;++t) {int t1=qr();if(t1)read[lg[t1]]=1;} int k=1;
while(k<=m) k<<=1;
poly::KSM(read,read,k,n);
//for(register int t=0;t<k;++t) cout<<read[t]<<' ';
//cout<<endl;
int ans=read[lg[x]];
printf("%d\n",ans);
return 0;
}

【题解】SDOI2015序列统计的更多相关文章

  1. [题解] [SDOI2015] 序列统计

    题面 题解 设 \(f[i][j]\) 代表长度为 \(i\) 的序列, 乘积模 \(m\) 为 \(j\) 的序列有多少个 转移方程如下 \[ f[i + j][C] = \sum_{A*B\equ ...

  2. [BZOJ 3992][SDOI2015]序列统计

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 2275  Solved: 1090[Submit][Stat ...

  3. 【LG3321】[SDOI2015]序列统计

    [LG3321][SDOI2015]序列统计 题面 洛谷 题解 前置芝士:原根 我们先看一下对于一个数\(p\),它的原根\(g\)有什么性质(好像就是定义): \(g^0\%p,g^1\%p,g^2 ...

  4. 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

    [BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...

  5. BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)

    3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...

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

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

  7. [SDOI2015]序列统计

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

  8. 3992: [SDOI2015]序列统计

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

  9. [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)

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

随机推荐

  1. RDS MySQL 8.0 语句级并发控制

    RDS MySQL 8.0 语句级并发控制 背景 为了应对突发的数据库请求流量,资源消耗过载的语句访问,SQL 访问模型的变化, 并保持 MySQL 实例持续稳定运行,AliSQL 版本设计了基于语句 ...

  2. @总结 - 2@ 位运算卷积/子集卷积 —— FWT/FMT

    目录 @0 - 参考资料@ @1 - 异或卷积概念及性质@ @2 - 快速沃尔什正变换(异或)@ @3 - 快速沃尔什逆变换(异或)@ @4 - 与卷积.或卷积@ @5 - 参考代码实现@ @6 - ...

  3. 12-2 js基础

    一 数据类型 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  4. Android 自定义界面的弹出框(可输入数据)

    上午写了一篇博文,介绍了如何定义从屏幕底部弹出PopupWindow,写完之后,突然想起之前写过自定义内容显示的弹出框,就随手写了两个实例,分享出来: 第一种实现方式:继承Dialog 1.1 线定义 ...

  5. 使用模块定义AngularJS组件

    一.模块创建/查找 module 当创建一个模块时,必须指定name和requires参数,即使你的模块并不存在依赖 var myApp=angular.module("exampleApp ...

  6. SpringMVC参数校验,包括JavaBean和基本类型的校验

    该示例项目使用SpringBoot,添加web和aop依赖. SpringMVC最常用的校验是对一个javaBean的校验,默认使用hibernate-validator校验框架.而网上对校验单个参数 ...

  7. 教你怎么让vi和vim显示行数

    首先我们来看看没有行号是多么难看. 2 再来看看有行号后的效果. 3 设置行号很简单. 我们要到命令模式下,输入set number :set number 按下回车 来看看效果 4 那么怎么关闭行号 ...

  8. 如何查看linux中的ssh端口开启状态

    netstat -anp |grep 22 netstat -anp |grep sshlsof -i :22

  9. 网易大数据平台的Spark技术实践

    网易大数据平台的Spark技术实践 作者 王健宗 网易的实时计算需求 对于大多数的大数据而言,实时性是其所应具备的重要属性,信息的到达和获取应满足实时性的要求,而信息的价值需在其到达那刻展现才能利益最 ...

  10. PHP IF判断 简写

    第一种:IF 条件语句 第二种:三元运算 第三种:&& .|| 组成的条件语句 第一种: IF 基础,相信绝大多数人都会: 第二种:  c=a>b ? true:false  / ...