题目


分析

首先朴素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]序列统计的更多相关文章

  1. 【洛谷3321_BZOJ3992】[SDOI2015]序列统计(原根_多项式)

    题目: 洛谷3321 分析: 一个转化思路比较神(典型?)的题-- 一个比较显然的\(O(n^3)\)暴力是用\(f[i][j]\)表示选了\(i\)个数,当前积在模\(m\)意义下为\(j\)的方案 ...

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

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

  3. [SDOI2015]序列统计(NTT+求原根)

    题目 [SDOI2015]序列统计 挺好的题!!! 做法 \(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\) 显然是可以快速幂的:\[f[2*i][j]=\sum\limi ...

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

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

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

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

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

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

  7. 【LG3321】[SDOI2015]序列统计

    [LG3321][SDOI2015]序列统计 题面 洛谷 题解 前置芝士:原根 我们先看一下对于一个数\(p\),它的原根\(g\)有什么性质(好像就是定义): \(g^0\%p,g^1\%p,g^2 ...

  8. [SDOI2015]序列统计

    [SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...

  9. 3992: [SDOI2015]序列统计

    3992: [SDOI2015]序列统计 链接 分析: 给定一个集和s,求多少个长度为n的序列,满足序列中每个数都属于s,并且所有数的乘积模m等于x. 设$f=\sum\limits_{i=0}^{n ...

  10. [BZOJ 3992][SDOI2015]序列统计

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 2275  Solved: 1090[Submit][Stat ...

随机推荐

  1. Excelize 开源基础发布 2.8.1 版本,2024 年首个更新

    Excelize 是 Go 语言编写的用于操作电子表格办公文档的开源基础库,基于 ISO/IEC 29500.ECMA-376 国际标准.可以使用它来读取.写入由 Microsoft Excel.WP ...

  2. gitee配置SSH公钥

    第一步,找个地方打开"git bash",然后输入生成ssh公钥的命令: ssh-keygen -t rsa -C 'your-email' 然后敲四次回车生成公钥: 第二步,输入 ...

  3. protobuf简单示例

    user.proto syntax = "proto3"; package demo; option go_package = "./pb"; //指定go_o ...

  4. auth模块的一些方法

    auth模块 auth模块是cookie和session的升级版,auth模块是对登录认证方法的一种封装,之前我们获取用户输入的用户名及密码后需要自己从user表里查询有没有用户名和密码符合的对象,而 ...

  5. git commit 不生成 changeId 解决方案

    1). 检查仓储 .git/hook 下面是否有 commit-msg 文件,如果没有可以到下面的地址下载,或者把其他同事的 commit-msg 文件拷贝到你的 .git/hook 重新commit ...

  6. 【LeetCode贪心#10】划分字母区间(有涉及hash数组的使用)

    划分字母区间 力扣题目链接(opens new window) 字符串 S 由小写字母组成.我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中.返回一个表示每个字符串片段的长度的列表 ...

  7. Autofac入门与替代ASP.NET Core、ABP依赖注入容器

    目录 Autofac 的使用 1,简单的实践 2,注册组件 3,Lambda 注册组件 4,注册泛型 5,属性注入 6,解析服务 7,生命周期 8,实例作用域 9,Autofac 其它需要学习的知识 ...

  8. STL-priority_queue模拟实现

    #include<deque> //测试用 #include<vector>//测试用 #include"9Date.h"//测试用 #include< ...

  9. Zabbix“专家坐诊”第183期问答汇总

    问题一 Q:老师,请问一下zabbix采集的数据怎么过滤,获取数据是nottime=20:30 notafter=3,怎么过滤出netafter=3 ?谢谢. A:过滤器设置如下图. 问题二 Q:大佬 ...

  10. centos 定时任务

    想法 看见一个别的项目,每天扒bing的背景,然后 生成个列表,然后数据就一天天的增加,创意非常好 有时间研究下 关键字 centos 定时任务 基于centos7系统定时任务创建 https://b ...