bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】
还是没有理解透原根……题目提示其实挺明显的,M是质数,然后1<=x<=M-1
这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法
首先因为0和任何数乘都是0,和其他数规则不相符,所以不考虑(答案也没让求)
然后看原根的性质,设g是M的原根,那么\( g^i%M 0<=i<M-1 \)就是1~M-1的不重集合,所以可以把乘法变成原根指数的加法,这样就变成多项式乘法了,可以用NTT优化
然后n非常大,所以使用快速幂进行多项式乘法
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=20005,mod=1004535809,g=3;
int n,m,x,k,s[N],d=2,id[N],lm,bt,re[N];
long long a[N],c[N],r[N];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void jia(long long &x,long long &y)
{
x+=y;
x>=mod?x-=mod:0;
}
long long ksm(long long a,long long b,int mod)
{
long long r=1;
while(b)
{
if(b&1)
r=r*a%mod;
a=a*a%mod;
b>>=1;
}
return r;
}
void dft(long long a[],int f)
{
for(int i=0;i<lm;i++)
if(i<re[i])
swap(a[i],a[re[i]]);
for(int i=1;i<lm;i<<=1)
{
long long wi=ksm(g,(mod-1)/(2*i),mod);
if(f==-1)
wi=ksm(wi,mod-2,mod);
for(int k=0;k<lm;k+=(i<<1))
{
long long w=1,x,y;
for(int j=0;j<i;j++)
{
x=a[j+k],y=1ll*w*a[i+j+k]%mod;
a[j+k]=((x+y)%mod+mod)%mod,a[i+j+k]=((x-y)%mod+mod)%mod;
w=w*wi%mod;
}
}
}
if(f==-1)
{
long long inv=ksm(lm,mod-2,mod);
for(int i=0;i<lm;i++)
a[i]=a[i]*inv%mod;
}
}
void ntt(long long a[],long long b[])
{
for(int i=0;i<lm;i++)
c[i]=b[i];
dft(a,1);
dft(c,1);
for(int i=0;i<lm;i++)
a[i]=a[i]*c[i]%mod;
dft(a,-1);
for(int i=m-1;i<lm;i++)
jia(a[i%(m-1)],a[i]),a[i]=0;
// for(int i=0;i<lm;i++)
// cerr<<a[i]<<" ";cerr<<endl;
}
int main()
{
n=read()-1,m=read(),x=read(),k=read();
for(int i=1;i<=k;i++)
s[i]=read();
for(bool fl=0;!fl;d++)
{
fl=1;
for(int i=1;i<m-1;i++)
if(ksm(d,i,m)==1)
{
fl=0;
break;
}
if(ksm(d,m-1,m)!=1)
fl=0;
if(fl)
break;
}
for(int i=0;i<m-1;i++)
id[ksm(d,i,m)]=i;//,cerr<<rl[i]<<" "<<i<<endl;
for(int i=1;i<=k;i++)
if(s[i])
a[id[s[i]]]++,r[id[s[i]]]++;
for(bt=0;(1<<bt)<=2*m;bt++);
lm=(1<<bt);
for(int i=0;i<lm;i++)
re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
while(n)
{
if(n&1)
ntt(r,a);
ntt(a,a);
n>>=1;
}
printf("%lld\n",r[id[x]]);
return 0;
}
bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】的更多相关文章
- 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]序列统计 【生成函数 + 多项式快速幂】
题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1155 Solved: 532[Submit][Statu ...
- 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: 2275 Solved: 1090[Submit][Stat ...
- BZOJ.3992.[SDOI2015]序列统计(DP NTT 原根)
题目链接 \(Description\) 给定\(n,m,x\)和集合\(S\).求\(\prod_{i=1}^na_i\equiv x\ (mod\ m)\)的方案数.其中\(a_i\in S\). ...
- 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 ...
随机推荐
- 【转载】读懂IL代码就这么简单(二)
一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...
- JQuery插件ajaxFileUpload 异步上传文件
一.先对ajaxFileUpload插件的语法参数进行讲解 原理:ajaxfileupload是通过监听iframe的onload方法来实现, 当从服务端处理完成后,就触发iframe的onload事 ...
- hud 1465、2049、2045 (递推)[含简单C(n,m) n!的写法]
C - 不容易系列之一 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- appium第一个安卓自动化工程
转自:https://university.utest.com/how-to-set-up-your-first-android-automation-project-with-appium/ App ...
- MFC 的 Picture Control 加载 BMP/PNG 图片的方法
1. 加载 BMP CStatic* pWnd = (CStatic*)GetDlgItem(IDC_PIC); // 得到 Picture Control 句柄 pWnd->ModifySty ...
- xamarin.Android 实现横向滚动导航
经过一段时间的练习,自己也做了不少的demo和一些小项目,今天就把这些demo分享给大家,也当做笔记记录到自己的博客中. 这次给大家带来的是HorizontalScrollView实现横向滑动,参考博 ...
- luogu3373 【模板】线段树2
题目大意: 已知一个数列,你需要进行下面三种操作:1.将某区间每一个数乘上x2.将某区间每一个数加上x3.求出某区间每一个数的和 本线段树的标记是个二元组:add和mul,其代表将一个线段中的每一个点 ...
- YTU 2866: 结构体---点坐标结构体
2866: 结构体---点坐标结构体 时间限制: 1 Sec 内存限制: 128 MB 提交: 499 解决: 344 题目描述 定义一个表示点坐标的结构体,输入两个点的坐标,输出这两个点中点的坐 ...
- 【转载】Java中StringTokenizer类的作用
StringTokenizer是一个用来分隔String的应用类,相当于VB的split函数.1.构造函数public StringTokenizer(String str)public String ...
- Viewpager animation duration setting
private void animatePagerTransition(final boolean forward) { ValueAnimator animator = ValueAnimator. ...