数学(快速数论变换):SDOI2015 序列统计
【题目描述】
小C有一个集合S,里面的元素都是小于M的非负整数。他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S。
小C用这个生成器生成了许多这样的数列。但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个。小C认为,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi。另外,小C认为这个问题 的答案可能很大,因此他只需要你帮助他求出答案mod 1004535809的值就可以了。
【输入格式】
一行,四个整数,N、M、x、|S|,其中|S|为集合S中元素个数。
第二行,|S|个整数,表示集合S中的所有元素。
【输出格式】
一行,一个整数,表示你求出的权值和mod 1004535809的值。
【样例输入】
4 3 1 2
1 2
【样例输出】
8
【提示】
对于10%的数据,1<=N<=1000;
对于30%的数据,3<=M<=100;
对于60%的数据,3<=M<=800;
对于全部的数据,1<=N<=10^9,3<=M<=8000,M为质数,0<=x<=M-1,输入数据保证集合S中元素不重复。
竟然没有x=0的数据。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=,G=;
const int MOD=;
int g,n,m,x,s,pos[N],num[N];
int Qpow(int x,int k,int mod){
long long ret=;
while(k){
if(k&)ret=1ll*ret*x%mod;
x=1ll*x*x%mod;k>>=;
}
return ret;
} void Rader(int *a,int len){
for(int i=,j=len>>;i<len-;i++){
if(i<j)swap(a[i],a[j]);
int k=len>>;
while(j>=k){
j-=k;
k>>=;
}
j+=k;
}
} void NTT(int *a,int len,int on){
Rader(a,len);
for(int h=,wn;h<=len;h<<=){
if(on==)wn=Qpow(G,(MOD-)/h,MOD);
else wn=Qpow(G,MOD--(MOD-)/h,MOD);
for(int j=;j<len;j+=h){
int w=,x,y;
for(int k=j;k<j+(h>>);k++){
x=a[k];y=1ll*a[k+(h>>)]*w%MOD;
a[k]=(x+y)%MOD;a[k+(h>>)]=(x-y+MOD)%MOD;
w=1ll*w*wn%MOD;
}
}
}
if(on==-){
int inv=Qpow(len,MOD-,MOD);
for(int i=;i<len;i++)
a[i]=1ll*a[i]*inv%MOD;
}
} int f[N],r[N],l=N/;
void Solve(){
for(int i=;i<N;i++)
r[i]=f[i];n-=;
while(n){
NTT(f,N,);
if(n&){
NTT(r,N,);
for(int i=;i<N;i++)r[i]=1ll*r[i]*f[i]%MOD;
NTT(r,N,-);
for(int i=m-;i<N;i++)(r[i%(m-)]+=r[i])%=MOD,r[i]=;
}
for(int i=;i<N;i++)f[i]=1ll*f[i]*f[i]%MOD;
NTT(f,N,-);
for(int i=m-;i<N;i++)(f[i%(m-)]+=f[i])%=MOD,f[i]=;
n>>=;
}
printf("%d\n",r[pos[x]]);
} void Solve_Zero(){int cnt=,ans;
for(int i=;i<=s;i++)if(!num[i])cnt++;
ans=Qpow(s,n,MOD)-Qpow(s-cnt,n,MOD);
printf("%d\n",ans);
}
int main(){
freopen("sdoi2015_sequence.in","r",stdin);
freopen("sdoi2015_sequence.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&x,&s);
for(int i=;i<=s;i++)
scanf("%d",&num[i]);
if(!x)Solve_Zero();
for(g=;g<m;g++){int i;
for(i=;i<m-;i++)
if(Qpow(g,i,m)==)
break;
if(i==m-&&Qpow(g,m-,m)==)break;
}
for(int i=;i<m;i++)
pos[Qpow(g,i,m)]=i%(m-);
for(int i=;i<=s;i++)
if(num[i])f[pos[num[i]]]++;
Solve();
return ;
}
数学(快速数论变换):SDOI2015 序列统计的更多相关文章
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂
[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...
- BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1155 Solved: 532[Submit][Statu ...
- BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)
3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...
- 【算法】快速数论变换(NTT)初探
[简介] 快速傅里叶变换(FFT)运用了单位复根的性质减少了运算,但是每个复数系数的实部和虚部是一个余弦和正弦函数,因此系数都是浮点数,而浮点数的运算速度较慢且可能产生误差等精度问题,因此提出了以数论 ...
- Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT
Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...
- [SDOI2015]序列统计
[SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...
- 3992: [SDOI2015]序列统计
3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...
- [SDOI2015]序列统计(NTT+求原根)
题目 [SDOI2015]序列统计 挺好的题!!! 做法 \(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\) 显然是可以快速幂的:\[f[2*i][j]=\sum\limi ...
- 【题解】SDOI2015序列统计
[题解]SDOI2015序列统计 来自永不AFO的YYB的推荐 这里是乘积,比较麻烦,不过由于给定的序列膜数是个小质数,所以可以\(O(m^2\log m)\)找原跟(实际上不需要这么多). 乘积有点 ...
随机推荐
- Android开发报错系列(一),java.lang.NullPointerException,at android.widget.ListView.setupChild
问题描述:运行代码是报空指针错误,java.lang.NullPointerException,at Android.widget.ListView.setupChild 问题定位:listview控 ...
- 第一章 Android体系与系统架构
1. Dalvik 和 ART(Android Runtime) 在Dalvik中应用好比是一辆可折叠的自行车,平时是折叠的,只有骑的时候,才需要组装起来用.在ART中应用好比是一辆组装好了的自行车, ...
- Navicat Premium 自动备份mysql和sqlserver
mysql篇: 1.点击计划 2.点击新建处理作业 3.选择需要备份的数据库,上级可用任务 4.点击保存按钮,输入保存文件名 5.保存后点击设置计划任务 6.计划里新建保存时间,应用后输入系统密码即可 ...
- teamview centos 配置
1.下载teamview centos版本,本人喜欢tar.gz版本,但是官网只有rpm版本,附件中即为官网下载的teamview11 官方下载地址:https://www.teamviewer.co ...
- Oracle11g数据库导入到oracle10g的解决方法
我想有很多人在工作和学习中遇到这样的一个问题,Oracle数据库服务器版本和本机版本不一致问题,你的本机要是比服务器的版本要高的话还好,如果你本机是10g服务器是11g的话,从11g导出来的数据库是导 ...
- Android 通信机制Message、Handler 的用法
Android中提供了通信机制,Message.Handler 等,Message用于在子线程中传递数据,Handler用于发送数据到主线程中, 下面介绍基于Message.Handler的计时器 i ...
- Asp与Asp.Net的区别
今天在网上看到一位朋友问asp与asp.net的区别.编辑本人也是从asp转型到.net来的,几年了,几乎都忘记了asp的存在,也说不出它们之间的区别,因为感觉两者是根本就没有联系,非要说有联系,那就 ...
- Prototype 模式
Prototype 模式提供了一个通过已存在对象进行新对象创建的接口(Clone) ,Clone()实现和具体的实现语言相关,在 C++中我们将通过拷贝构造函数实现之. /////////////// ...
- 关于Function()函数对象的那些小九九
概念:首先,函数是一种特殊类型的数据,函数也是数据类型的一种,实际上函数也是一种对象,函数对象的内建构造器是Function(); 函数的几种创建方式: 函数声明法: function sum(a,b ...
- 解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误
重新启动服务器,访问web服务发现无法浏览,登陆服务器之 后进到nginx使用./nginx -s reload重新读取配置文件,发现报nginx: [error] open() "/usr ...