【bzoj3992】 SDOI2015—序列统计
http://www.lydsy.com/JudgeOnline/problem.php?id=3992 (题目链接)
题意
集合${S}$中有若干个不超过${m}$的非负整数,问由这些数组成一个长度${n}$的序列,使序列中的数的乘积对${m}$取模正好等于${x}$,问存在多少方案。
Solution
好神的题。算法还是要多复习,我连${NTT}$都忘记怎么写了T_T
这还是我的第一发原根→_→。
一个数如果有原根,那么它会有很多原根,所以如果对时间没有特殊限制,我们枚举${rt=2~~to~~inf}$,然后判断是否存在${t<m-1}$使${rt^t=1}$。虽然我并不知道为什么可以那样check。。
我们可以很简单的列出dp方程${f_{i,j}}$表示,已经放到了第${i}$个数,它们的乘积是${j}$的方案数。转移也就很显然了:$${f[i][j]=\sum_{k=1}^{m-1}f_{i-1,j*inv[k]}}$$
复杂度${O(nm^2)}$,于是我们就可以获得10分的高分,是不是很良心啊。
考虑这个东西怎么优化,我们把每一个${j}$都写成${m}$的原根的几次方,然后乘就变成加辣,然后我们就可以卷积辣。
然后你发现${n}$有${10^9}$,我们快速幂一波,然后就AC辣。
细节
一开始没想清没注意到还是循环卷积卧槽T_T
代码
// bzoj3992
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define LL long long
#define inf (1ll<<30)
#define MOD 1004535809
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=20010;
int f[maxn],g[maxn],rev[maxn],vis[maxn];
int n,m,rt,S,X,N,L; int power(int a,int b,int c) {
int res=1;
while (b) {
if (b&1) res=(LL)res*a%c;
b>>=1;a=(LL)a*a%c;
}
return res;
}
void root(int p) {
if (p==2) {rt=1;return;}
for (rt=2;;rt++) {
int flag=1;
for (int i=2;i*i<p;i++)
if (power(rt,(p-1)/i,p)==1) {flag=0;break;}
if (flag) break;
}
}
namespace NTT {
LL A[maxn],B[maxn];
void NTT(LL *a,int f) {
for (int i=0;i<N;i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;i<N;i<<=1) {
LL gn=power(3,(MOD-1)/(i<<1),MOD);
for (int p=i<<1,j=0;j<N;j+=p) {
LL g=1;
for (int k=0;k<i;k++,(g*=gn)%=MOD) {
LL x=a[k+j],y=g*a[k+j+i]%MOD;
a[k+j]=(x+y)%MOD,a[k+j+i]=(x-y+MOD)%MOD;
}
}
}
if (f==-1) reverse(a+1,a+N);
}
void Init(int *a,int *b) {
for (int i=0;i<N;i++) A[i]=a[i],B[i]=b[i];
NTT(A,1);NTT(B,1);
for (int i=0;i<N;i++) (A[i]*=B[i])%=MOD;
NTT(A,-1);
LL ev=power(N,MOD-2,MOD);
for (int i=0;i<N;i++) (A[i]*=ev)%=MOD;
for (int i=0;i<m-1;i++) a[i]=(A[i]+A[i+m-1])%MOD;
}
}
using namespace NTT; int main() {
scanf("%d%d%d%d",&n,&m,&X,&S);
root(m);
for (int x,i=1;i<=S;i++) scanf("%d",&x),vis[x]=1;
for (int p=1,i=0;i<m-1;i++,(p*=rt)%=m) if (vis[p]) f[i]=1;
for (N=1,L=-1;N<(m-1)*2;N<<=1) L++;
for (int i=0;i<N;i++) rev[i]=(rev[i>>1]>>1) | ((i&1)<<L);
g[0]=1;
while (n) {
if (n&1) Init(g,f);
n>>=1;Init(f,f);
}
for (int i=0,p=1;i<m-1;i++,(p*=rt)%=m)
if (p==X) {printf("%d",g[i]);break;}
return 0;
}
【bzoj3992】 SDOI2015—序列统计的更多相关文章
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- BZOJ3992: [SDOI2015]序列统计
Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...
- 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− ...
- 【动态规划】bzoj3992 [Sdoi2015]序列统计 10分
#include<cstdio> using namespace std; #define MOD 1004535809 int a[8001],f[1001][101],n,m,x,S; ...
- 【NTT】bzoj3992: [SDOI2015]序列统计
板子题都差点不会了 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生 ...
- BZOJ3992 [SDOI2015]序列统计 【生成函数 + 多项式快速幂】
题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...
- 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂
[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- [SDOI2015]序列统计
[SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...
随机推荐
- 20155227《网络对抗》Exp4 恶意代码分析
20155227<网络对抗>Exp4 恶意代码分析 实践目标 1.是监控你自己系统的运行状态,看有没有可疑的程序在运行. 2.是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分 ...
- 20155318 Exp1 PC平台逆向破解(5)M
20155318 Exp1 PC平台逆向破解(5)M 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入 ...
- libgdx学习记录21——Box2d物理引擎之碰撞Contact、冲量Impulse、关节Joint
Box2d中,物体可以接受力(Force).冲量(Impulse)和扭矩(Torque).这些物理元素都能改变物体的运动形式,并且默认都会唤醒物体,当然只是针对动态物体. 力是一个持久的效果,通过Bo ...
- Eclipse编辑器设置
1. 自己不太喜欢Eclipse按回车后自动插入参数的默认选项. 可以在Window-Preferences-Java-Editor-Content Assist选项里,将Fill method ar ...
- Django中的cookie和session
前言 HTTP协议 是短连接.且状态的,所以在客户端向服务端发起请求后,服务端在响应头 加入cokie响应给浏览器,以此记录客户端状态: cook是来自服务端,保存在浏览器的键值对,主要应用于用户登录 ...
- 博客配置Racket代码字体
我想在博客园的文章中插入Racket代码,但是博客园的代码块和高亮都太难看了,如果能把scribble/manual的CSS文件中的Racket代码块的配置拿出来就可以有漂亮的Racket代码高亮了, ...
- raft--分布式一致性协议
0. 写在前面的话 一直从事分布式对象存储工作,在分布式对象存储的运营,开发等工作中,数据一致性是至关重要的.因此想写一篇关于分布式一致性的文章.一来,可以和大家分享.二来,可以提高自己的文字提炼能力 ...
- This is me
This is me 爱琴棋 爱书画 也爱格物 爱跋山 爱涉水 也爱深林 This is me. 刘伯承的诗词有曰“高耸入云”,于是“李入云”便成为了我一生的标记,也造就了一个时而安静,时而疯狂的我 ...
- Redis学习笔记之Redis的对象
类型与编码: typedef struct redisObject { unsigned type:4://类型 unsigned encod ...
- 《Linux内核分析与实现》 第四周 读书笔记
第五章 系统调用 20135307 张嘉琪 5.1 与内核通信 系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: 它为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳 ...