[SDOI2015]序列统计(NTT+求原根)
题目
挺好的题!!!
做法
\(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\)
显然是可以快速幂的:$$f[2*i][j]=\sum\limits_{ab\equiv j(mod~ M)}f[i][a]\cdot f[i][b]$$
时间复杂度\(O(m^2 log n)\)
考虑转换到对数上则可以化乘为加,而\(M\)为质数,原根\(g\)的\(g_0^{m-2}\)恰好对应\([1,m-1]\)
我们用这些代替数\(g^A\equiv a,g^B\equiv b,g^J\equiv j(mod~m)\)
相当于把\([1,m-1]\)通过这种方法映射到\([0,m-2]\),再进行数组初始化
\]
根据费马小定理\(g^a\equiv g^{a~mod~M-1}(mod~M)\),则:$$f[2*i][j]=\sum\limits_{g^{A+BmodM-1}= g^{Jmod M-1}}f[i][a]\cdot f[i][b]$$
\]
则化成了卷积的形式,而后面的取模,我们先正常做一下卷积,然后\(f[i][j]=f[i][j]+f[i][j+M-1]\)
Code
#include<bits/stdc++.h>
typedef int LL;
const LL Mod=1004535809,maxn=1e6+9,G=3;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3)+(x<<1)+c-'0'; c=getchar();
}return x*f;
}
LL n,m,g,x,num;
LL prime[maxn],r[maxn],c[maxn],d[maxn],pos[maxn],F[maxn],H[maxn];
inline LL Pow(LL base,LL b,LL mod){
LL sum(1);
while(b){
if(b&1) sum=1ll*sum*base%mod; base=1ll*base*base%mod; b>>=1;
}return sum;
}
inline LL Get_g(LL N){
LL p(--N),tot(0);
for(LL i=2;i*i<=N;++i){
if(N%i==0){
while(N%i==0) N/=i;
prime[++tot]=i;
}
}
if(N>1) prime[++tot]=N;
LL now(2);
while(true){
bool flag(false);
for(LL i=1;i<=tot;++i)
if(Pow(now,p/prime[i],p+1)==1){
flag=true;
break;
}
if(!flag) return now;
++now;
}
}
inline LL Init(LL N){
LL limit(1),len(0);
while(limit<N){
limit<<=1; ++len;
}
for(LL i=0;i<limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<len-1);
return limit;
}
inline void NTT(LL *a,LL limit,LL type,LL mod=Mod){
for(LL i=0;i<limit;++i) if(i<r[i]) std::swap(a[i],a[r[i]]);
for(LL mid=1;mid<limit;mid<<=1){
LL wn(Pow(G,(mod-1)/(mid<<1),mod));
if(type==-1) wn=Pow(wn,mod-2,mod);
for(LL R=mid<<1,j=0;j<limit;j+=R){
for(LL k=0,w=1;k<mid;++k,w=1ll*w*wn%mod){
LL x(a[j+k]),y(1ll*w*a[j+mid+k]%mod);
a[j+k]=1ll*(x+y)%mod;
a[j+mid+k]=1ll*(x-y+mod)%mod;
}
}
}
if(type==-1){
LL now(Pow(limit,mod-2,mod));
for(LL i=0;i<limit;++i) a[i]=1ll*a[i]*now%mod;
}
}
inline void Mul(LL *a,LL *b,LL limit,LL N,LL mod=Mod){
for(LL i=0;i<limit;++i) c[i]=a[i];
for(LL i=0;i<limit;++i) d[i]=b[i];
NTT(c,limit,1); NTT(d,limit,1);
for(LL i=0;i<limit;++i) c[i]=1ll*c[i]*d[i]%mod;
NTT(c,limit,-1);
for(LL i=0;i<N-1;++i) c[i]=1ll*(c[i]+c[i+N-1])%mod;
for(LL i=0;i<N-1;++i) a[i]=c[i];
}
int main(){
n=Read(); m=Read(); x=Read(); num=Read();
g=Get_g(m);
for(LL i=0;i<m-1;++i) pos[Pow(g,i,m)]=i;
for(LL i=1;i<=num;++i){
LL val(Read());
if(val) ++F[pos[val]];
}
H[pos[1]]=1;
LL limit(Init(2*m));
while(n){
if(n&1) Mul(H,F,limit,m); Mul(F,F,limit,m); n>>=1;
}
printf("%d\n",H[pos[x]]);
return 0;
}
[SDOI2015]序列统计(NTT+求原根)的更多相关文章
- 【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 ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- bzoj 3992: [SDOI2015]序列统计 NTT+原根
今天开始学习丧心病狂的多项式qaq...... . code: #include <bits/stdc++.h> #define ll long long #define setIO ...
- 【BZOJ】3992: [SDOI2015]序列统计 NTT+生成函数
[题意]给定一个[0,m-1]范围内的数字集合S,从中选择n个数字(可重复)构成序列.给定x,求序列所有数字乘积%m后为x的序列方案数%1004535809.1<=n<=10^9,3< ...
- bzoj 3992 [SDOI2015]序列统计——NTT(循环卷积&&快速幂)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 有转移次数.模M余数.方案数三个值,一看就是系数的地方放一个值.指数的地方放一个值.做 ...
- bzoj 3992 [SDOI2015] 序列统计 —— NTT (循环卷积+快速幂)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 (学习NTT:https://riteme.github.io/blog/2016-8 ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)
3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...
随机推荐
- C#用户控件实战01_CSS布局
很多应用系统的主页布局,一般采用如下案例所示布局较多,如下图的CSS布局框架,上.中.下,接下来我们演示,在C#中实现如下的业务架构布局. 代码范例: 在<body></body&g ...
- ubuntu下安装软件时报错解决:Unmet dependencies. Try 'apt-get -f install' with no packages
在错误后面运行以下代码,补全依赖项: sudo apt-get -f install
- linux 系统运维工具13款
1. 查看进程占用带宽情况 - Nethogs Nethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽. 下载:http://sourceforge.net/projects/ ...
- Docker 镜像 && 容器的基本操作
镜像 && 容器 docker 镜像好比操作系统的镜像(iso) docker 容器好比是已安装运行的操作系统 所以说 docker 镜像文件运行起来之后,就是我们所说的 docker ...
- elementui限制开始日期和结束日期
项目需求:开始日期和结束日期 禁用当前日期之前的日期.同时结束日期 禁用开始日期之前的日期 <div class='startTime'> 开始时间:<el-date-picker ...
- TensorFlow实现Softmax Regression识别手写数字
本章已机器学习领域的Hello World任务----MNIST手写识别做为TensorFlow的开始.MNIST是一个非常简单的机器视觉数据集,是由几万张28像素*28像素的手写数字组成,这些图片只 ...
- Mysql之数据库简介
一.什么是数据库? 据库即存放数据的仓库,只不过这个仓库是在计算机存储设备上,而且数据是按一定的格式存放的 过去人们将数据存放在文件柜里,现在数据量庞大,已经不再适用 数据库是长期存放在计算机内.有组 ...
- ubuntu---记录.动态库默认路径的踩坑
发现这个问题,还是经过一个报错问题卡了好多天,然后请求好多人的支援,最后个人的疑问:为什么明明指明了路径,生成 .SO 没有问题,在调用.SO 就有问题,报错各种找不到函数或者未定义,然后把缺的 *. ...
- 改进Bert----spanBERT
SpanBert:对 Bert 预训练的一次深度探索 SpanBERT: Improving Pre-training by Representing and Predicting Spans 解读S ...
- unable to access 'https://github.com/shixianqing/img.git/': SSL connect error 解决办法
解决在linux环境下,git clone 项目,走https协议时,报SSL connect error 错误 升级nss yum update -y nss curl libcurl