题目

[SDOI2015]序列统计

挺好的题!!!

做法

\(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]\),再进行数组初始化

\[f[2*i][j]=\sum\limits_{g^{A+B}\equiv g^J(mod~ M)}f[i][a]\cdot f[i][b]
\]

根据费马小定理\(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[2*i][j]=\sum\limits_{A+B\equiv J(mod~ 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+求原根)的更多相关文章

  1. 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

    [BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...

  2. BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1155  Solved: 532[Submit][Statu ...

  3. BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)

    题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...

  4. bzoj 3992: [SDOI2015]序列统计 NTT+原根

    今天开始学习丧心病狂的多项式qaq......    . code: #include <bits/stdc++.h> #define ll long long #define setIO ...

  5. 【BZOJ】3992: [SDOI2015]序列统计 NTT+生成函数

    [题意]给定一个[0,m-1]范围内的数字集合S,从中选择n个数字(可重复)构成序列.给定x,求序列所有数字乘积%m后为x的序列方案数%1004535809.1<=n<=10^9,3< ...

  6. bzoj 3992 [SDOI2015]序列统计——NTT(循环卷积&&快速幂)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 有转移次数.模M余数.方案数三个值,一看就是系数的地方放一个值.指数的地方放一个值.做 ...

  7. bzoj 3992 [SDOI2015] 序列统计 —— NTT (循环卷积+快速幂)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 (学习NTT:https://riteme.github.io/blog/2016-8 ...

  8. [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1888  Solved: 898[Submit][Statu ...

  9. BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)

    3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...

随机推荐

  1. 谷歌浏览器调用activex控件方法

    原文转自 https://jingyan.baidu.com/article/af9f5a2d0ebe5543140a4596.html activex是由微软开发,所以在支持上,目前原生态支持的只有 ...

  2. 线程二(Monitor)

    Monitor 类的命名空间是 System.Threading,它的用法和 lock 本质是一样的. 使用 Monitor 类锁定资源的代码如下. Monitor.Enter(object); tr ...

  3. 我们为什么要用redis

    Redis的5要点: 1.为什么要选择Redis:介绍Redis的使用场景与使用Redis的原因: 2.Redis常用命令总结:包括时间复杂度总结与具体数据类型在Redis内部使用的数据结构: 3.R ...

  4. 【转载】 C#使用string.Join快速用特定字符串串联起数组

    在C#中有时候我们的数组元素需要通过一些特定的字符串串联起来,例如将整形Int数组通过逗号快速串联起来成为一个字符串,可以使用String.Join方法.或者一个字符串string类型数组所有元素快速 ...

  5. 编写一个stm32 svc关中断函数

    做到了让stm32触发svc中断并传递进去参数然后切换到handler模式并修改特殊寄存器的值,从而达到关中断,但是其实这个程序直接就是特权级,故不进入handler模式也可以修改特殊寄存器..... ...

  6. 如何在github上提交pr

    如何在github上提交pr 1.fork开源的代码到自己的远程仓库 2.clone自己的仓库到本地电脑 3.与源代码的github仓库建立新的连接 git remote add upstream h ...

  7. Android笔记(十七) Android中的Service

    定义和用途 Service是Android的四大组件之一,一直在后台运行,没有用户界面.Service组件通常用于为其他组件提供后台服务或者监控其他组件的运行状态,例如播放音乐.记录地理位置,监听用户 ...

  8. python生成器学习

    python生成器学习: 案例分析一: def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) #(i for i in d ...

  9. 吾爱破解 Happy_New_Year_2019_Challenge 第二题

    题目在这里面找 https://down.52pojie.cn/Challenge/Happy_New_Year_2019_Challenge.rar 内容方面参考论坛上的文章,并做了一些补充 htt ...

  10. grep redis-cli command

    https://www.reddit.com/r/redis/comments/atfvqy/how_to_grep_from_monitor_command/ _------------------ ...