Description

题库链接

给出集合 \(S\) ,元素都是小于 \(M\) 的非负整数。问能够生成出多少个长度为 \(N\) 的数列 \(A\) ,数列中的每个数都属于集合 \(S\) ,并且

\[\prod_{i=1}^N A_i\equiv x \pmod{M}\]

答案对 \(1004535809\) 取模。

\(1\leq N\leq 10^9,3\leq M\leq 8000, M 为质数,0\leq x\leq M-1\)

Solution

显然能够得到 \(DP\) 的解法:令 \(f_{i,j}\) 为生成序列长度为 \(i\) 时,乘积在模 \(M\) 意义下为 \(j\) 的方案数。

显然 \(f_{i,j}\rightarrow f_{i+1,(j\times w)\mod M},w\in S\) 。

但 \(n\leq 10^9\) 显然不能递推。考虑优化。

由于乘法不太好搞,我们试着换种思路,我们不妨将集合内数取 \(\log\) 。那么 \(f_{i,\log j}\rightarrow f_{i+1,\log j+\log w},w\in S\) 。

但实数域上确实不好做,考虑取离散对数。由费马小定理,它是以 \(M-1\) 为周期的,那么只要 \(\text{NTT}\) 优化,加上快速幂。对模意义外的数讨论即可。

Code

#include <bits/stdc++.h>
using namespace std;
const int yzh = 1004535809;
const int N = 8000*4; int n, m, x, s, G, lg[N+5], a, len, L, R[N+5];
int A[N+5]; int quick_pow(int a, int b, int yzh) {
int ans = 1;
while (b) {
if (b&1) ans = 1ll*a*ans%yzh;
b >>= 1, a = 1ll*a*a%yzh;
}
return ans;
}
void get_G() {
int prime[N+5], tot = 0, x = m-1;
for (int i = 2, lim = sqrt(x)+1; i <= lim; i++)
if (x%i == 0) {
prime[++tot] = i;
while (x%i == 0) x /= i;
}
if (x != 1) prime[++tot] = x;
for (int i = 2; true; i++) {
int flag = 1;
for (int j = 1; j <= tot; j++)
if (quick_pow(i, (m-1)/prime[j], m) == 1) {
flag = 0; break;
}
if (flag == 1) {G = i; break; }
}
for (int i = 1, g = G; i < m; i++, g = 1ll*g*G%m) lg[g] = i;
}
void NTT(int *A, int o) {
for (int i = 0; i < len; i++) if (i < R[i]) swap(A[i], A[R[i]]);
for (int i = 1; i < len; i <<= 1) {
int gn = quick_pow(3, (yzh-1)/(i<<1), yzh), x, y;
if (o == -1) gn = quick_pow(gn, yzh-2, yzh);
for (int j = 0; j < len; j += (i<<1)) {
int g = 1;
for (int k = 0; k < i; k++, g = 1ll*g*gn%yzh) {
x = A[j+k], y = 1ll*g*A[j+k+i]%yzh;
A[j+k] = (x+y)%yzh, A[j+k+i] = (x-y+yzh)%yzh;
}
}
}
if (o == 1) return;
for (int i = 0, inv = quick_pow(len, yzh-2, yzh); i < len; i++)
A[i] = 1ll*A[i]*inv%yzh;
for (int i = m; i < len; i++) (A[i%(m-1) ? i%(m-1) : m-1] += A[i]) %= yzh, A[i] = 0;
}
void NTTpow(int *A, int b) {
int ans[N+5] = {0}; ans[0] = 1;
while (b) {
NTT(A, 1);
if (b&1) {
NTT(ans, 1);
for (int i = 0; i < len; i++) ans[i] = 1ll*ans[i]*A[i]%yzh;
NTT(ans, -1);
}
for (int i = 0; i < len; i++) A[i] = 1ll*A[i]*A[i]%yzh;
NTT(A, -1); b >>= 1;
}
for (int i = 0; i < len; i++) A[i] = ans[i];
}
void work() {
scanf("%d%d%d%d", &n, &m, &x, &s); get_G();
for (int i = 1; i <= s; i++) {scanf("%d", &a); ++A[lg[a]]; }
A[0] = 0;
for (len = 1; len <= (m<<1); len <<= 1) ++L;
for (int i = 0; i < len; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1));
NTTpow(A, n); printf("%d\n", A[lg[x]]);
}
int main() {work(); return 0; }

[SDOI 2015]序列统计的更多相关文章

  1. [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)

    [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...

  2. BZOJ 3992 [SDOI 2015] 序列统计 解题报告

    这个题最暴力的搞法就是这样的: 设 $Dp[i][j]$ 为前 $i$ 个数乘积为 $j$ 的方案数. 转移的话就不多说了哈... 当前复杂度 $O(nm^2)$ 注意到,$M$ 是个质数,就说明 $ ...

  3. [BZOJ 3992] [SDOI 2015] 序列统计

    Description 传送门 Solution [一] 设 \(f[i][j]\) 表示前 \(i\) 个数的乘积在模 \(p\) 意义下等于 \(j\) 的方案数,有 \[ f[i][j]=\su ...

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

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

  5. Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和

    下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...

  6. Bzoj 4403: 序列统计 Lucas定理,组合数学,数论

    4403: 序列统计 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 328  Solved: 162[Submit][Status][Discuss] ...

  7. BZOJ4403 序列统计—Lucas你好

    绝对是全网写的最详细的一篇题解  题目:序列统计 代码难度:简单 思维难度:提高+-省选 讲下题面:给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量.输出答案 ...

  8. BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]

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

  9. [SDOI2015]序列统计

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

随机推荐

  1. 『练手』通过注册表 获取 VS 和 SQLServer 文件路径

    获取任意 VS 和 SQLServer 的 磁盘安装目录. 背景需求:如果磁盘电脑安装了 VS 或者 SQLServer 则 认定这台计算机 的使用者 是一名 软件研发人员,则让程序 以最高权限运行. ...

  2. Beta 第七天

    今天遇到的困难: 构造新适配器的时候出现了某些崩溃的问题 ListView监听器有部分的Bug 今天完成的任务: 陈甘霖:完成相机调用和图库功能,完成阿尔法项目遗留下来的位置调用问题,实现百度定位 蔡 ...

  3. 201621123040 《Java程序设计》第1周学习总结

    1.本周学习总结 关键词 JAVA概述 HelloWorld JDK JRE JVM JAVA基础语法 相关联系 通过一周的学习,我对JAVA有了初步的了解,JAVA是一种优秀的跨平台编写代码的应用平 ...

  4. 单向链表在O(1)时间内删除一个节点

    说删链表节点,第一时间想到就是遍历整个链表,找到删除节点的前驱,改变节点指向,删除节点,但是,这样删除单链表的某一节点,时间复杂度就是O(n),不符合要求: 时间复杂度是O(n)的做法就不说了,看看O ...

  5. Mysql数据库的触发程序

    /** **创建表 */ CREATE TABLE test1(a1 INT); CREATE TABLE test2(a2 INT); CREATE TABLE test3(a3 INT NOT N ...

  6. Struts2之配置文件中Action的详细配置(续)

    承接上一篇 4.处理结果的配置 Action类的实例对象调用某个方法,处理完用户请求之后,将返回一个逻辑视图名的字符串.核心Filter收到返回的逻辑视图名字符串,根据struts.xml中的逻辑视图 ...

  7. js 点击 返回顶部 动画

    附上效果图 触发前 触发后 HTML代码: CSS代码 JS代码 由于复制文本太丑了 所以直接放的图片  但是我在评论区把js代码又复制了一边 以便你们使用

  8. Ubuntu命令行连接WPA/WPA2无线网线

    一,连接无加密无线网络zhang:sudo ip link set wlan0 up sudo iw dev wlan0 connect zhangsudo dhclient wlan0 二,连接WP ...

  9. 什么是KMP算法?KMP算法推导

    花了大概3天时间,了解,理解,推理KMP算法,这里做一次总结!希望能给看到的人带来帮助!! 1.什么是KMP算法? 在主串Str中查找模式串Pattern的方法中,有一种方式叫KMP算法 KMP算法是 ...

  10. 常用cmd代码片段及.net core打包脚本分享

    bat基础命令 注释:rem 注释~~ 输出:echo hello world 接收用户输入:%1 %2,第n个变量就用%n表示 当前脚本路径:%~dp0 当前目录路径:%cd% 设置变量:set c ...