BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂
3992: [SDOI2015]序列统计
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 1155 Solved: 532
[Submit][Status][Discuss]
Description
Input
一行,四个整数,N、M、x、|S|,其中|S|为集合S中元素个数。第二行,|S|个整数,表示集合S中的所有元素。
Output
一行,一个整数,表示你求出的种类数mod 1004535809的值。
Sample Input
1 2
Sample Output
HINT
Source
想法:
设a[i]表示数字i是否属于集合S,C[i]表示数列之积%M=i的方案数。 当n=2时:
c[(i*j)%M]=∑a[i]*a[j]
令A[i]=a[g^i],C[i]=c[g^i]//∵g为M原根,遍历0~M-1,而将数组映射到另一个数组,并不影响答案,只要改变运算规则。
由 c[g^(i+j)%M]=∑a[g^i]*a[g^j] 得到:
C[(i+j)%(M-1)]=∑A[i]*A[j]//费马小定理:g^(M-1)
∴每次FFT后将后面的累加到前面来就行了。
当n=y时,C=A^y,找到g^j=x,输出C[j] 于是NTT+快速幂O(nlog^2n)
#include<cstdio>
#define ll long long
const int MP(),lem(),g();
int n,m,x,size,gm;
int a[lem+],num,p[],tp;
struct data{int a[lem+];}A,C,B;
int power(int a,int b,int MP)
{
ll t=,y=a;b+=b<?MP-:;
for(;b;b>>=,y=(y*y)%MP)if(b&)t=(t*y)%MP;
return (int)t;
}
bool check(int y)
{
for(int j=;j<=tp;j++)
if(power(y,(m-)/p[j],m)==)return false;
return true;
}
void Get_g(int x)
{
if(!(x&))
{
p[++tp]=;
while(!(x&))x>>=;
}
for(int i=;i*i<=x;i+=)
{
if(x%i==)
{
p[++tp]=i;
while(x%i==)x/=i;
}
}
if(x>)p[++tp]=x;
for(int i=;i<=m-;i++)
if(check(i)){gm=i;break;}
}
int R[lem+],w[lem+],wn,l,il,h;
void deal()
{
l=;w[]=;
while(l<=m+m)l<<=,h++;
for(int i=;i<l;i++)R[i]=(R[i>>]>>|(i&)<<(h-));
il=power(l,MP-,MP);
}
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
void NTT(int *a,int l,int ty)
{
for(int i=;i<l;i++)if(i<R[i])swap(a[i],a[R[i]]);
for(int leng=;leng<=l;leng<<=)
{
int M=leng>>;
wn=power(g,ty*(MP-)/leng,MP);
for(int i=;i<M;i++)w[i]=(1ll*w[i-]*wn)%MP;
for(int i=;i<l;i+=leng)
{
for(int j=;j<M;j++)
{
int x=a[i+j],y=(1ll*w[j]*a[i+j+M])%MP;
a[i+j]=x+y;a[i+j+M]=x-y;
a[i+j]-=a[i+j]>=MP?MP:;
a[i+j+M]+=a[i+j+M]<?MP:;
}
}
}
if(ty==-)
for(int i=;i<l;i++)a[i]=(1ll*a[i]*il)%MP;
}
void three(data &A,data &B)
{
NTT(A.a,l,);NTT(B.a,l,);
for(int i=;i<l;i++)B.a[i]=(1ll*B.a[i]*A.a[i])%MP;
NTT(B.a,l,-);
for(int i=m-;i<l;i++)B.a[i%(m-)]=(B.a[i%(m-)]+B.a[i])%MP,B.a[i]=;
}
void run()
{
C.a[]=;
while(n)
{
if(n&)
{
B=A;
three(B,C);
}
B=A;
three(B,A);
n>>=;
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&x,&size);
for(int i=;i<=size;i++){scanf("%d",&num);a[num]=;}
Get_g(m-);deal();
for(int i=,j=;i<m-;i++,j=(j*gm)%m)
{
A.a[i]=a[j];
if(j==x)num=i;
}
run();
printf("%d",C.a[num]);
return ;
}
BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂的更多相关文章
- 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 ...
- bzoj 3992: [SDOI2015]序列统计 NTT+原根
今天开始学习丧心病狂的多项式qaq...... . code: #include <bits/stdc++.h> #define ll long long #define setIO ...
- BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)
3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- [BZOJ 3992][SDOI2015]序列统计
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 2275 Solved: 1090[Submit][Stat ...
- bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】
还是没有理解透原根--题目提示其实挺明显的,M是质数,然后1<=x<=M-1 这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法 首先因为0和任何数乘都是0 ...
- 【BZOJ】3992: [SDOI2015]序列统计 NTT+生成函数
[题意]给定一个[0,m-1]范围内的数字集合S,从中选择n个数字(可重复)构成序列.给定x,求序列所有数字乘积%m后为x的序列方案数%1004535809.1<=n<=10^9,3< ...
- BZOJ.3992.[SDOI2015]序列统计(DP NTT 原根)
题目链接 \(Description\) 给定\(n,m,x\)和集合\(S\).求\(\prod_{i=1}^na_i\equiv x\ (mod\ m)\)的方案数.其中\(a_i\in S\). ...
随机推荐
- 如何在VS2015中使用Git命令提示符
本文转载自 http://qkxue.net/info/176223/Visual-Studio-Git VS2015自带了Git插件,但有时候觉得Git控制台命令更方便些.VS中本身不能把Git B ...
- UVa 10534 Wavio Sequence (LIS+暴力)
题意:给定一个序列,求一个最长子序列,使得序列长度为奇数,并且前一半严格递增,后一半严格递减. 析:先正向和逆向分别求一次LIS,然后再枚举中间的那个数,找得最长的那个序列. 代码如下: #pragm ...
- 如何快速编写大项目的Makefile文件
在构建C++的后台服务时,经常需要自己来编写makefile文件,而如果没有合适的方法或模板时,编写makefile文件是一件很费时费力的事情.因此,为了帮助程序员高效准确的编写makefile文件, ...
- [51nod] 1091 线段的重叠 贪心
X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]. 给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长 ...
- 图论1 Tarjan算法
强连通分量 模板(强联通分量个数+缩点) #include<iostream> #include<cstdio> #define MAXn 100000 #define MAX ...
- VBA for AutoCAD
Download the Microsoft Visual Basic for Applications Module (VBA) 2016 Downloads AutoCAD 2016 VBA mo ...
- vue+element级联选择器对接后台数据
1.后台接口返回的数据肯定要和级联选择器的数据一致,所以我专门弄个model存放返回的值,如下:/** * @Auther: GGDong * @Date: 2019/4/3 10:30 */@Get ...
- UVA - 1330 City Game
InputThe rst line of the input le contains an integer K | determining the number of datasets. Next l ...
- 【BZOJ 2243】染色
传送门:洛谷 BZOJ 还不会LCT的小伙伴可以看一下这篇博客:LCT总结 我初学动态树时就是看着那篇博客学的,写的很好! 那好 言归正传. 显然树上 x 到 y 的路径的问题都可以用LCT Ac ...
- C 语言实例 - 判断字母
C 语言实例 - 判断字母 C 语言实例 C 语言实例 用户输入一个字符,判断该字符是否为一个字母. 实例 #include <stdio.h> int main() { char c; ...