[SD2015]序列统计——solution

http://www.lydsy.com/JudgeOnline/problem.php?id=3992
很容易得出DP方程:
f[i][c]=f[i-1][a]*f[1][b]①
其中a*b%M=c
f第一位为当前数列长度,第二维为当前数列模M意义下的乘积
考虑从一开始就剔除第二维为0的情况——把它单独考虑,一来她好算,二来她不影响其他结果
若将f[i-1][a]展开;
则:
$$f[i][c]=\sum_{a_1=1}^M\sum_{a_2=1}^M...\sum_{a_i=1}^M([\Pi_{j=1}^ia_j(mod)M=c]\Pi_{j=1}^if[1][a_j])$$②
把f[1]的所有第二维取值得出的结果构造为多项式,记为$f_1(x)$
$$f_1(x)=map[0]x^0+map[1]x^1+map[2]x^2...map[m-1]x^{m-1}$$③
其中,map[i]为i数字在S中出现的次数,同样的,map[i]=f[1][i]
于是:
$$f_i(x)=\sum_{j=1}^{m-1}a_{i,j}*x^j$$④
其中$$a_{i,j}=\sum_{x=kj}\sum_{d|x}a_{i-1,d}*a_{1,{x \over d}}$$
当然$a_{x,y}=f[x][y]$
于是发现①,是多项式在模意义下的狄利克雷卷积;
而②,则是其在模意义下的狄利克雷卷积的乘幂
然而这个东西不能快速运算;
尝试转换这些式子;
看①,发现c取值在1到M-1之间,而$g^x$(其中g为M的原根)在x取0到M-2时可取遍1到M-1
不妨依此改写①
设$g^{e_x}=x$
$$f[i][g^{e_c}]=f[i-1][g^{e_a}]*f[1][g^{e_b}],e_c=(e_a+e_b)(mod)(M-1)$$
$$ff[i][e_c]=ff[i-1][e_a]*f[1][e_b],e_c=(e_a+e_b)(mod)(M-1)$$⑤
ff与f同构,求f[i][x]等价于求ff[i][e_x];
于是发现⑤,是多项式在模意义下的卷积;
NTT计算,加多项式取模;
如果把ff写成类似f的②的形式,则他是多项式在模意义下的卷积的乘幂;
快速幂优化
总效率$O(M*log_2M*log_2N)$
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define LL long long
using namespace std;
const LL mod=;
int N,M,X,S,len;
int rat[],map[],b[];
LL a[],ans[],g[],aa[];
LL Sqr_num(LL ,int );
void get_b(int );
void Sqr(int );
void pol_mul(LL a[],LL b[]);
int get_len(int );
void ra(LL f[]);
void NTT(LL f[],int t);
int main(){
int i,j,k;
scanf("%d%d%d%d",&N,&M,&X,&S);
for(i=;i<=S;i++){
scanf("%d",&j);
map[j]++;
}
if(X==){
printf("%lld",(Sqr_num(S,N)+mod-Sqr_num(S-map[],N))%mod);
return ;
}
get_b(M);M--;
for(i=;i<=M;i++)
a[b[i]%(M)]=map[i]%mod;
Sqr(N);
printf("%lld",ans[b[X]%M]);
return ;
}
LL Sqr_num(LL x,int n){
LL ret=;
while(n){
if(n&)(ret*=x)%=mod;
n>>=;(x*=x)%=mod;
}
return ret;
}
void get_b(int p){
int i,j,f=,ij,g;
for(i=;i<p;i++){
ij=;f=;
for(j=;j<p;j++){
(ij*=i)%=p;
if(j!=p-&&ij%p==)
break;
else
if(j==p-&&ij%p==)
f=;
}
if(f){
g=i;break;
}
}
ij=;
for(i=;i<p;i++){
(ij*=g)%=p;
b[ij]=i;
}
}
void Sqr(int n){
int i,fl=;
len=get_len(M);
rat[]=;
for(i=;i<len;i++)
rat[i]=rat[i>>]>>|((i&)*(len>>));
while(n){
if(n&){
if(!fl){
for(i=;i<M;i++)ans[i]=a[i];
fl=;
}
else
pol_mul(ans,a);
}
n>>=;
for(i=;i<M;i++)
aa[i]=a[i];
pol_mul(a,aa);
}
}
void pol_mul(LL a[],LL b[]){
int i,j,k;
for(i=M;i<len;i++)
a[i]=,b[i]=;
NTT(a,);NTT(b,);
for(i=;i<len;i++)
a[i]=a[i]*b[i]%mod;
NTT(a,-);NTT(b,-);
for(i=;i<M;i++)
a[i]=(a[i]+a[i+M])%mod;
}
int get_len(int n){
int ret=;
while(ret<(n<<))ret<<=;
return ret;
}
void ra(LL f[]){
int i;
for(i=;i<len;i++)
if(rat[i]>i)
swap(f[i],f[rat[i]]);
}
void NTT(LL f[],int t){
int i,j,k,lim;
int f0,f1;
ra(f);
for(k=;k<=len;k<<=){
lim=k>>;
g[]=;
g[]=Sqr_num(,t>?(mod-)/k:mod--(mod-)/k);
for(i=;i<lim;i++)
g[i]=g[i-]*g[]%mod;
for(i=;i<len;i+=k){
for(j=i;j<i+lim;j++){
f0=f[j];f1=g[j-i]*f[j+lim]%mod;
f[j]=(f0+f1)%mod;f[j+lim]=(f0-f1+mod)%mod;
}
}
}
if(t<){
LL inv=Sqr_num(len,mod-);
for(i=;i<len;i++)
(f[i]*=inv)%=mod;
}
}
[SD2015]序列统计——solution的更多相关文章
- [SDOI2015]序列统计
[SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...
- Bzoj 4403: 序列统计 Lucas定理,组合数学,数论
4403: 序列统计 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 328 Solved: 162[Submit][Status][Discuss] ...
- BZOJ4403 序列统计—Lucas你好
绝对是全网写的最详细的一篇题解 题目:序列统计 代码难度:简单 思维难度:提高+-省选 讲下题面:给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量.输出答案 ...
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- 【BZOJ3992】序列统计(动态规划,NTT)
[BZOJ3992]序列统计(动态规划,NTT) 题面 BZOJ 题解 最裸的暴力 设\(f[i][j]\)表示前\(i\)个数,积在膜意义下是\(j\)的方案数 转移的话,每次枚举一个数,直接丢进去 ...
- 【BZOJ4403】序列统计(组合数学,卢卡斯定理)
[BZOJ4403]序列统计(组合数学,卢卡斯定理) 题面 Description 给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量.输出答案对10^6+3取 ...
- BZOJ 3992 【SDOI2015】 序列统计
题目链接:序列统计 我来复习板子了……这道题也是我写的第一发求原根啊? 求原根方法: 从小到大依次枚举原根.设当前枚举的原根为\(x\),模数为\(p\),\(p-1\)的质因数分别为\(p_1,p_ ...
- bzoj 4403 序列统计 卢卡斯定理
4403:序列统计 Time Limit: 3 Sec Memory Limit: 128 MB Description 给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调 ...
- 3992: [SDOI2015]序列统计
3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...
随机推荐
- 极其简单的用JS在浏览器中创建下载文件的方法
有这样一个需求,在js中动态创建一个页面,然后下载该页面为word文档,研究了一上午,最后发现实现起来如此简单. 在js中创建如下方法:(直接复制即可) function downloadFile(f ...
- JDK下载与安装、 Eclipse下载与使用的总结心得_20173311118_牛明旺
一.JDK下载与安装心得: ① 从官网http://www.oracl.com/technetwork/java上下载JDK,注意一定要同意该网站上的协议,否则下载不了(即点击“Accept Lic ...
- 基于Django+celery二次开发动态配置定时任务 ( 二)
一.需求 结合上一篇,使用djcelery模块开发定时任务时,定时任务的参数都保存在djcelery_periodictask表的args.kwargs字段里,并且是json格式.那么,当定时任务多了 ...
- shell-009:删除字母
把一个文件里的前100行中有字母的行删除:再把101-200行的字母去掉 #!bin/bashsed '101.200s/[a-zA-Z]//g' filesed -n '1.100'p file | ...
- 配置不同站点不同版本PHP
Apache 配置 1.常规手动部署apache方法(不会apache配置的请先移步看下Apache基本手工配置方法),解压fcgid,取其mod_fcgid.so至modules目录 2.打开htt ...
- 关于 unsigned long long 于 long long
long long 最大只有19位 : unsigned long long 最大有20位 ,原因牺牲了符合位来换取更大的记录
- [转] String to Date conversion in hive - 在 Hive 中各种字符串转换成日期格式
[From] http://bigdataprogrammers.com/string-date-conversion-hive/ Please refer below table to conver ...
- RocketMQ消息发送的队列选择与容错策略
一个topic有多个队列,分散在不同的broker.producer在发送消息的时候,需要选择一个队列 producer发送消息全局时序图: 队列选择与容错策略结论: 在不开启容错的情况下,轮询队列进 ...
- RocketMQ详解
原文链接:http://www.cnblogs.com/xiaodf/p/5075167.html 简介 官方简介: RocketMQ是一款分布式.队列模型的消息中间件,具有以下特点: 能够保证严格 ...
- Mac 10.12常用软件清单
链接: https://pan.baidu.com/s/1slds1OD 密码: 7m5t 配套教程:http://www.cnblogs.com/EasonJim/tag/mac/ 如果失效了,联系 ...