#NTT,原根#洛谷 3321 JZOJ 4051 [SDOI2015]序列统计
分析
首先朴素dp方程
设\(dp[i][j]\)表示\(i\)个数的数列乘积为\(j\)的方案
那么\(dp[i][j*a[k]\bmod m]=itself+dp[i-1][j]\)
这可以用矩阵乘法优化到\(O(m^3log_2n)\),然而考场真的不想写
其实这个方程不明显,考虑到\(n\)超级大,不是矩阵乘法就是快速幂(推测)
能不能用2的多少次方拼凑出长度为\(n\)的数列
刚刚的方程可以变为$$dp[2i][t]=\sum_{xy\bmod m==t}dp[i][x]+dp[i][y]$$
那乘法怎么办呢,用原根把乘法变成加法,那就可以用NTT做了
至于原根我不好解释,但是原根会比较小,
具体做法就是\(g^k\neq 1(k|p-1)\)那么\(g\)就是\(p\)的一个原根(准确来说应该是\(\varphi(p)\),但是这里是质数)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int mod=1004535809,invG=334845270,N=8011;
int n,r[N<<2],inv1,inv2,m,G,F[N<<2],Ans[N<<2],fi[N],KsM,S,X;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed ksm(int x,int y,int p){
rr int ans=1;
for (;y;y>>=1,x=1ll*x*x%p)
if (y&1) ans=1ll*ans*x%p;
return ans;
}
inline signed Getroot(int p){
for (rr int g=2;;++g){
rr bool flag=1;
for (rr int i=2;i*i<p;++i)
if ((p-1)%i==0&&(ksm(g,i,p)==1||ksm(g,(p-1)/i,p)==1)) flag=0;
if (flag) return g;
}
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline void ntt(int *f,int op){
for (rr int i=0;i<n;++i)
if (i<r[i]) swap(f[i],f[r[i]]);
for (rr int p=2;p<=n;p<<=1){
rr int len=p>>1,w=ksm(op==1?3:invG,(mod-1)/p,mod);
for (rr int i=0;i<n;i+=p)
for (rr int j=i,t=1;j<i+len;++j,t=1ll*t*w%mod){
rr int z=1ll*f[len+j]*t%mod;
f[len+j]=mo(f[j],mod-z),f[j]=mo(f[j],z);
}
}
}
inline void cheng(int *c,int *a,int *b){
rr int f[N<<2],g[N<<2],C[N<<2];
for (rr int i=0;i<n;++i) f[i]=a[i],g[i]=b[i];
ntt(f,1),ntt(g,1); for (rr int i=0;i<n;++i) f[i]=1ll*f[i]*g[i]%mod;
ntt(f,-1); for (rr int i=0;i<n;++i) f[i]=1ll*f[i]*inv1%mod;
for (rr int i=0;i<m-1;++i) C[i]=mo(f[i],f[i+m-1]);
for (rr int i=0;i<n;++i) c[i]=C[i];
}
signed main(){
KsM=iut(),m=iut(),X=iut(),S=iut(),G=Getroot(m),fi[1]=0;
for (rr int i=1,t=1;i<m-1;++i) fi[t=t*G%m]=i;
for (rr int i=1;i<=S;++i){
rr int t=iut();
if (t) ++F[fi[t]];
}
Ans[0]=1;
for (n=1;n<=2*m-2;n<<=1); inv1=ksm(n,mod-2,mod);
for (rr int i=0;i<n;++i) r[i]=(r[i>>1]>>1)|((i&1)?n>>1:0);
for (;KsM;KsM>>=1,cheng(F,F,F)) if (KsM&1) cheng(Ans,Ans,F);
printf("%d",Ans[fi[X]]);
return 0;
}
#NTT,原根#洛谷 3321 JZOJ 4051 [SDOI2015]序列统计的更多相关文章
- 【洛谷3321_BZOJ3992】[SDOI2015]序列统计(原根_多项式)
题目: 洛谷3321 分析: 一个转化思路比较神(典型?)的题-- 一个比较显然的\(O(n^3)\)暴力是用\(f[i][j]\)表示选了\(i\)个数,当前积在模\(m\)意义下为\(j\)的方案 ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- [SDOI2015]序列统计(NTT+求原根)
题目 [SDOI2015]序列统计 挺好的题!!! 做法 \(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\) 显然是可以快速幂的:\[f[2*i][j]=\sum\limi ...
- 【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 ...
- BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)
3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...
- 【LG3321】[SDOI2015]序列统计
[LG3321][SDOI2015]序列统计 题面 洛谷 题解 前置芝士:原根 我们先看一下对于一个数\(p\),它的原根\(g\)有什么性质(好像就是定义): \(g^0\%p,g^1\%p,g^2 ...
- [SDOI2015]序列统计
[SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...
- 3992: [SDOI2015]序列统计
3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...
- [BZOJ 3992][SDOI2015]序列统计
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 2275 Solved: 1090[Submit][Stat ...
随机推荐
- java面向对象之封装-继承-抽象-多态-组合五种概念及用法一网打尽
说明 曾经在学习java面向对象时,你是否会为面向对象的封装-继承-抽象-多态-组合等各种概念搞得稀里糊涂,乃至反复阅读,背诵其相关概念,结果一段时间过后又还给了时间... 这种经历简直令人发指,让人 ...
- 案例分享:Qt工程机械真空激光焊接系统软件产品定制(西门子PLC,mysql数据库,用户权限控制,界面配置,参数定制,播放器,二维图标,rgv小车,期限控制,参数调试等)
需求 1.触摸屏控制,按照客户需求,ui由本司美工承担设计,显示分辨率1280 x 1024,同时支持鼠标操作. 2.权限控制:三种权限,分为管理员(可以定制模块界面,修改产品名称等定制化软件和 ...
- mac上安装vue
安装node.js brew install nodejs node -v #查看版本 给nodejs模块安装目录设置访问权限 sudo chmod -R 777 /usr/local/lib/nod ...
- Kotlin 协程二 —— 通道 Channel
目录 一. Channel 基本使用 1.1 Channel 的概念 1.2 Channel 的简单使用 1.3 Channel 的迭代 1.4 close 关闭 Channel 1.5 Channe ...
- Centos系统下,各种服务重启
1.sudo systemctl start firewalld 2../redis-server /usr/local/bin/redis.conf 3.mongod -f /etc/mongod ...
- 【Azure Redis 缓存】使用StackExchange.Redis,偶发ERROR - Timeout performing HSET (15000ms)
问题描述 使用StackExchange.Redis 作为Redis客户端SDK,连接Azure Redis服务,长期运行后发现,每天都偶发 Timeout Error. 错误消息如下: StackE ...
- 【Openxml】如何为OpenXml元素创建超链接
已知在OpenXml有以下几种超链接 功能 说明 跳转页面 跳转某一页:ppaction://hlinksldjump跳转第一页:ppaction://hlinkshowjump?jump=first ...
- Vue3学习(二十一)- 文档管理页面布局修改
写在前面 按照国际惯例,要先聊下生活,吐槽一番,今天是2月14日,也是下午听老妈说,我才知道! 现在真的是对日期节日已经毫无概念可言,只知道星期几. 现在已经觉得写博客也好,学习文章也罢,和写日记一样 ...
- C++ //STL---常用算法 //常用遍历 for_each //transform
1 //STL---常用算法 2 //常用遍历 for_each 3 //transform 4 #include<iostream> 5 #include<string> 6 ...
- C++中的不规则二维数组
技术背景 最近刚学习C++的一些编程技巧,对于一些相对比较陌生的问题,只能采取一些简单粗暴的方案来实现.就比如说,我们可以在Python中定义一个[[0,0,0],[1,2],[1,1,1],[3]] ...