[SDOI2015]序列统计(NTT+求原根)
题目
挺好的题!!!
做法
\(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\)
显然是可以快速幂的:$$f[2*i][j]=\sum\limits_{ab\equiv j(mod~ M)}f[i][a]\cdot f[i][b]$$
时间复杂度\(O(m^2 log n)\)
考虑转换到对数上则可以化乘为加,而\(M\)为质数,原根\(g\)的\(g_0^{m-2}\)恰好对应\([1,m-1]\)
我们用这些代替数\(g^A\equiv a,g^B\equiv b,g^J\equiv j(mod~m)\)
相当于把\([1,m-1]\)通过这种方法映射到\([0,m-2]\),再进行数组初始化
\]
根据费马小定理\(g^a\equiv g^{a~mod~M-1}(mod~M)\),则:$$f[2*i][j]=\sum\limits_{g^{A+BmodM-1}= g^{Jmod M-1}}f[i][a]\cdot f[i][b]$$
\]
则化成了卷积的形式,而后面的取模,我们先正常做一下卷积,然后\(f[i][j]=f[i][j]+f[i][j+M-1]\)
Code
#include<bits/stdc++.h>
typedef int LL;
const LL Mod=1004535809,maxn=1e6+9,G=3;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3)+(x<<1)+c-'0'; c=getchar();
}return x*f;
}
LL n,m,g,x,num;
LL prime[maxn],r[maxn],c[maxn],d[maxn],pos[maxn],F[maxn],H[maxn];
inline LL Pow(LL base,LL b,LL mod){
LL sum(1);
while(b){
if(b&1) sum=1ll*sum*base%mod; base=1ll*base*base%mod; b>>=1;
}return sum;
}
inline LL Get_g(LL N){
LL p(--N),tot(0);
for(LL i=2;i*i<=N;++i){
if(N%i==0){
while(N%i==0) N/=i;
prime[++tot]=i;
}
}
if(N>1) prime[++tot]=N;
LL now(2);
while(true){
bool flag(false);
for(LL i=1;i<=tot;++i)
if(Pow(now,p/prime[i],p+1)==1){
flag=true;
break;
}
if(!flag) return now;
++now;
}
}
inline LL Init(LL N){
LL limit(1),len(0);
while(limit<N){
limit<<=1; ++len;
}
for(LL i=0;i<limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<len-1);
return limit;
}
inline void NTT(LL *a,LL limit,LL type,LL mod=Mod){
for(LL i=0;i<limit;++i) if(i<r[i]) std::swap(a[i],a[r[i]]);
for(LL mid=1;mid<limit;mid<<=1){
LL wn(Pow(G,(mod-1)/(mid<<1),mod));
if(type==-1) wn=Pow(wn,mod-2,mod);
for(LL R=mid<<1,j=0;j<limit;j+=R){
for(LL k=0,w=1;k<mid;++k,w=1ll*w*wn%mod){
LL x(a[j+k]),y(1ll*w*a[j+mid+k]%mod);
a[j+k]=1ll*(x+y)%mod;
a[j+mid+k]=1ll*(x-y+mod)%mod;
}
}
}
if(type==-1){
LL now(Pow(limit,mod-2,mod));
for(LL i=0;i<limit;++i) a[i]=1ll*a[i]*now%mod;
}
}
inline void Mul(LL *a,LL *b,LL limit,LL N,LL mod=Mod){
for(LL i=0;i<limit;++i) c[i]=a[i];
for(LL i=0;i<limit;++i) d[i]=b[i];
NTT(c,limit,1); NTT(d,limit,1);
for(LL i=0;i<limit;++i) c[i]=1ll*c[i]*d[i]%mod;
NTT(c,limit,-1);
for(LL i=0;i<N-1;++i) c[i]=1ll*(c[i]+c[i+N-1])%mod;
for(LL i=0;i<N-1;++i) a[i]=c[i];
}
int main(){
n=Read(); m=Read(); x=Read(); num=Read();
g=Get_g(m);
for(LL i=0;i<m-1;++i) pos[Pow(g,i,m)]=i;
for(LL i=1;i<=num;++i){
LL val(Read());
if(val) ++F[pos[val]];
}
H[pos[1]]=1;
LL limit(Init(2*m));
while(n){
if(n&1) Mul(H,F,limit,m); Mul(F,F,limit,m); n>>=1;
}
printf("%d\n",H[pos[x]]);
return 0;
}
[SDOI2015]序列统计(NTT+求原根)的更多相关文章
- 【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 ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- bzoj 3992: [SDOI2015]序列统计 NTT+原根
今天开始学习丧心病狂的多项式qaq...... . code: #include <bits/stdc++.h> #define ll long long #define setIO ...
- 【BZOJ】3992: [SDOI2015]序列统计 NTT+生成函数
[题意]给定一个[0,m-1]范围内的数字集合S,从中选择n个数字(可重复)构成序列.给定x,求序列所有数字乘积%m后为x的序列方案数%1004535809.1<=n<=10^9,3< ...
- 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 ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)
3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...
随机推荐
- SqlServer2008 / SqlServer2012 禁用windows登录,sa忘记密码或密码过期如何登陆
以管理员身份运行cmd 1.cmd 下 停止SqlServer服务,net stop mssqlserver: 2.新建windows账号test,加入administrators组里,授予管理员权 ...
- python day1 python介绍,安装及运算符
目录 python day1 1. 不同编程语言的对比 2. 为什么学python? 3. python的种类 4. python的安装(windows系统) 5. 导入模块或包 6. pyc文件 7 ...
- 【已解决】极速迅雷win10闪退解决方案
[已解决]极速迅雷win10闪退解决方案 本文作者:天析 作者邮箱:2200475850@qq.com 发布时间: Wed, 17 Jul 2019 18:01:00 +0800 在吾爱下载了个极速迅 ...
- STM8 定时器
中断映射表 对应stm8_interrupt.c #pragma vector=1 __interrupt void TRAP_IRQHandler(void) { } #pragma vector= ...
- [LeetCode] 1029. 两地调度 ☆(贪心)
官方题解 作差排序 描述 公司计划面试 2N 人.第 i 人飞往 A 市的费用为 costs[i][0],飞往 B 市的费用为 costs[i][1]. 返回将每个人都飞到某座城市的最低费用,要求每个 ...
- Win10设置开机进入启动设置模块(进入安全模式等)
Win10设置开机进入启动设置模块(进入安全模式等) Win10系统要进入安全模式或其他启动模式选择时,需要在系统中做如下设置后,才可在开机的时候对模式进行选择,操作如下: 1.依次点选:win10设 ...
- Scyther Advanced Topics
建立非对称秘钥对 声明一个公钥函数和一个私钥函数: const pk2: Function ; const sk2: Function : 我们还声明这些函数代表非对称密钥对: inversekeys ...
- 团队第六次作业-Beta冲刺及发布说明
1.相关信息 Q A 作业所属课程 https://edu.cnblogs.com/campus/xnsy/2019autumnsystemanalysisanddesign/ 作业要求 https: ...
- Java反射中Class.forName和classloader的区别
Java中Class.forName和classloader都可以用来对类进行加载. Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块 ...
- 实例演示MaxTenuringThreshold参数及阈值动态调整策略
在上一次[https://www.cnblogs.com/webor2006/p/11031563.html]学习了一个新的JVM对象晋升到老年代的参数“MaxTenuringThreshold”,它 ...