【SDOI2015】序列统计 解题报告
2119: 【BZOJ3992】【SDOI2015】序列统计
Description
小\(C\)有一个集合\(S\),里面的元素都是小于\(M\)的非负整数。
他用程序编写了一个数列生成器,可以生成一个长度为\(N\)的数列,数列中的每个数都属于集合\(S\)。
小\(C\)用这个生成器生成了许多这样的数列。但是小\(C\)有一个问题需要你的帮助:给定整数\(x\),求所有可以生成出的,且满足数列中所有数的乘积\(\bmod M\)的值等于\(x\)的不同的数列的有多少个。
小\(C\)认为,两个数列\(\{A_i\}\)和\(\{B_i\}\)不同,当且仅当至少存在一个整数\(i\),满足\(A_i≠B_i\)。另外,小\(C\)认为这个问题的答案可能很大,因此他只需要你帮助他求出答案\(\bmod 1004535809\)的值就可以了。
Input
一行,四个整数,\(N\)、\(M\)、\(x\)、\(|S|\),其中\(|S|\)为集合\(S\)中元素个数。
第二行,\(|S|\)个整数,表示集合\(S\)中的所有元素。
Output
一行,一个整数,表示你求出的种类数\(\bmod 1004535809\)的值。
HINT
对于\(10\%\)的数据,\(1≤N≤1000\);
对于\(30\%\)的数据,\(3≤M≤100\);
对于\(60\%\)的数据,\(3≤M≤800\);
对于全部的数据,\(1≤N≤10^9\),\(3≤M≤8000\),\(M\)为质数,\(1≤x≤M−1\),输入数据保证集合\(S\)中元素不重复
先吐槽一波部分分吧...
明显有一个矩阵快速幂的做法,然后通过不了60pts,请问这个点的分怎么拿呢?
\(dp_{i,j}\)前\(i\)个数乘积为\(j\)的方案
\]
思路:利用原根转换问题,然后生成函数用多项式快速幂求一下就行了。
对原根,若\(g\)是\(m\)的原根,则\(g^0,g^1,\dots,g^{\varphi(m)-1}\)遍历\(\bmod m\)的最小剩余系,就是它们有个一一对应关系
关于求原根,把\(\varphi(m)-1\)分解质因数得到每个质因子\(p_i\),然后从小到大枚举原根\(g\),检验每个质因子是否有\(g^{\frac{\varphi(m)-1}{p_i}}\equiv 1 \pmod m\),如果所有质因子都没有,\(g\)就是原根,因为原根非常的小,所以这个复杂度是正确的。
然后把前面\(ab\%m=j\)换掉,就成了\((a’+b')\%(m-1)=j'\)
然后你构造生成函数\(f_i=\sum is_ix^{i-1}\),\(is_i\)代表最开始转换后这个值存不存在。
然后发现结果就是这个\(\tt f^n\),写一个\(NTT\)快速幂就成了,复杂度\(O(m\log m\log n)\)
Code:
#include <cstdio>
#include <algorithm>
const int N=(1<<14)+10;
const int mod=1004535809,Gi=334845270;
#define add(x,y,p) ((x+y)%p)
#define mul(x,y,p) (1ll*(x)*(y)%p)
int qp(int d,int k,int p){int f=1;while(k){if(k&1) f=mul(f,d,p);d=mul(d,d,p),k>>=1;}return f;}
int A[N],B[N],F[N],D[N],n,m,turn[N],to[N],len=1;
int GetG(int x)
{
int s[1010]={0},phi=x-1,t=x-1;
for(int i=2;i*i<=t;i++)
{
if(t%i==0)
{
s[++s[0]]=i;
while(t%i==0) t/=i;
}
}
if(t!=1) s[++s[0]]=t;
for(int i=2;i<x;i++)
{
int flag=1;
for(int j=1;j<=s[0];j++)
if(qp(i,phi/s[j],x)==1)
{
flag=0;
break;
}
if(flag) return i;
}
return -1;
}
void NTT(int *a,int typ)
{
for(int i=0;i<len;i++) if(i<turn[i]) std::swap(a[i],a[turn[i]]);
for(int le=1;le<len;le<<=1)
{
int wn=qp(typ?3:Gi,(mod-1)/(le<<1),mod);
for(int p=0;p<len;p+=le<<1)
{
int w=1;
for(int i=p;i<p+le;i++,w=mul(w,wn,mod))
{
int tx=a[i],ty=mul(w,a[i+le],mod);
a[i]=add(tx,ty,mod);
a[i+le]=add(tx,mod-ty,mod);
}
}
}
if(!typ)
{
int inv=qp(len,mod-2,mod);
for(int i=0;i<len;i++) a[i]=mul(a[i],inv,mod);
}
}
void Rev()
{
int L=-1;for(int i=1;i<len;i<<=1) ++L;
for(int i=1;i<len;i++) turn[i]=turn[i>>1]>>1|(i&1)<<L;
}
void polymul(int *a,int *b)
{
for(int i=0;i<len;i++) A[i]=a[i],B[i]=b[i],a[i]=0;
NTT(A,1),NTT(B,1);
for(int i=0;i<len;i++) A[i]=mul(A[i],B[i],mod);
NTT(A,0);
for(int i=0;i<len;i++) a[i%(m-1)]=add(a[i%(m-1)],A[i],mod);
}
int main()
{
int s,x;
scanf("%d%d%d%d",&n,&m,&x,&s);
int g=GetG(m);
while(len<=(m<<1))len<<=1;Rev();
for(int f=1,i=0;i<m-1;i++,f=mul(f,g,m))
to[f]=i;
for(int x,i=1;i<=s;i++)
{
scanf("%d",&x);
if(x) F[to[x]]=1,D[to[x]]=1;
}
--n;
while(n)
{
if(n&1) polymul(F,D);
polymul(D,D);
n>>=1;
}
printf("%d\n",F[to[x]]);
return 0;
}
2018.12.17
【SDOI2015】序列统计 解题报告的更多相关文章
- BZOJ 3992 [SDOI 2015] 序列统计 解题报告
这个题最暴力的搞法就是这样的: 设 $Dp[i][j]$ 为前 $i$ 个数乘积为 $j$ 的方案数. 转移的话就不多说了哈... 当前复杂度 $O(nm^2)$ 注意到,$M$ 是个质数,就说明 $ ...
- 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\). ...
- 3992: [SDOI2015]序列统计
3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...
- [BZOJ 3992][SDOI2015]序列统计
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 2275 Solved: 1090[Submit][Stat ...
- 【LG3321】[SDOI2015]序列统计
[LG3321][SDOI2015]序列统计 题面 洛谷 题解 前置芝士:原根 我们先看一下对于一个数\(p\),它的原根\(g\)有什么性质(好像就是定义): \(g^0\%p,g^1\%p,g^2 ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[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 ...
随机推荐
- 零基础学python之函数与模块(附详细的代码和安装发布文件过程)
代码重用——函数与模块 摘要:构建函数,创建模块,安装发布文件,安装pytest和PEP 8插件,确认PEP8兼容性以及纠错 重用代码是构建一个可维护系统的关键. 代码组是Python中对块的叫法. ...
- ADO.net中DataTable的应用
一.思维导图 二.知识点描述 (1)构造函数 DataTable() 不带参数初始化DataTable类的新实例 DataTable(string tableName) 用指定的表名初始化DataT ...
- 最优方向法(MOD)
算法描述 求解模型: \[\min\sum\limits_i\|x_i\|_0 \quad \mathrm{s.t.} \; \|Y-DX\|^2_F \leq \varepsilon\] 或 \[\ ...
- 07-matplotlib-箱线图
import numpy as np import matplotlib.pyplot as plt ''' 箱形图(Box-plot)又称为盒须图,盒式图,或 箱线图: 是一种用在显示一组数据分散情 ...
- JDK自带的监控工具方法
一.概述 SUN 的JDK中的几个工具,非常好用.秉承着有免费,不用商用的原则.以下简单介绍一下这几种工具.(注:本文章下的所有工具都存在JDK5.0以上版本的工具集里(jdk的bin目录 ...
- YQCB冲刺第二周第二天
今天的任务依然为实现查看消费明细的功能. 遇到的问题为从数据库中分类读取,实现图标的显示. 站立会议为: 任务面板为:
- Prism6下的MEF:添加Logger
上篇已经简单的构建了一个Prism的程序,现在我们需要添加一个Logger,Prism本身自带一个功能简单的TextLogger,但是我们希望能用.Net常用的Log4net.所以我们需要重载掉Boo ...
- 10th 本周工作量及进度统计
本周PSP C(类别) C(内容) S(开始时间) ST(结束时间) I(中断时间) T(实际时间) 文档 11月22日 规格说明书练习 10:23 15:30 132 175 11月23日 知识点 ...
- 课堂作业:alpha发布点评
1. 新蜂 项目:游戏俄罗斯方块 基础玩法已实现,部分功能尚不完备,总的来说已经很出色了.不过希望下降加速那部分可以优化一下,不要按住↓加速,而是按一下就使当前方块加速下落至底部就好了. 2. 天 ...
- 获取php版本
phpversion()函数可以获取版本 version_compare可以比较两个版本 mixed version_compare ( string $version1 , string $vers ...