[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 ...
随机推荐
- GCD介绍:Dispatch_source
[转自:GCD介绍(三): Dispatch Sources] 何为Dispatch Sources 简单来说,dispatch source是一个监视某些类型事件的对象.当这些事件发生时,它自动将一 ...
- iOS学习笔记(4)——显示单组件选取器
1. 创建工程 创建新工程,create a new Xcode project 创建single view application 创建名为PickerViewTest的工程 2. 创建xib文件 ...
- 设计简单登录界面(Java web)
程序设计思想: 在Input.jsp中创建一个表格里边分别是课程名称,任课老师,教学地点,并分别用三个文本框来接受输入的三个属性, 并传到另外的Jsp页面中,又来接受三个数据,并判断传来的教师,与教室 ...
- BERT和ULMFIT embedding比较文本分类结果
Instructions [THIS REPOSITORY IS UNDER DEVELOPMENT AND MOER DATASETS AND MODELS WILL BE ADDED] [FEEL ...
- JS框架设计之对象类型判断一种子模块
Javascript有两套数据类型,一套是基础数据类型,一套是对象数据类型.基础数据类型包括5种基本数据类型,分别是null,bool,undefined,number,string,也叫简单数据类型 ...
- 1.TypeError: must be str, not bytes
1.TypeError: must be str, not bytes错误: 解答: 写文件处 open(filename, 'w').write 应该写为 open(filename, 'wb'). ...
- 003javascript语句
javascript语句和java差不多,注意==和===区别 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" " ...
- Jquery动画操作的stop()函数
今天做一个点击动画时,遇到了当快速连续点击时,动画效果会乱,并不是我们想要达到的效果. 查询了一下,确认是动画累积的原因.网上搜了一下,发现jquery 的stop()函数刚好能解决. stop(cl ...
- ActiveMQ:Exception occurred while processing this request, check the log for more information!
出现上面错误的原因有以下两种 1 jdk的版本和activemq的版本不符 安装完ActiveMQ之后,通过http://IP:8161登陆到控制台. 通过测试代码给服务端发送队列消息,在控制台点击q ...
- 多线程编程(二)-Exchanger的使用
Exchanger的介绍 类Exchanger的功能可以使两个线程之间传输数据. 方法exchange()的使用 package com.wjg.unit; import java.util.conc ...