Description

传送门

Solution

〖一〗

设 \(f[i][j]\) 表示前 \(i\) 个数的乘积在模 \(p\) 意义下等于 \(j\) 的方案数,有

\[f[i][j]=\sum_{k=0}^{p-1}f[i-1][k]\cdot h[j\cdot k^{-1}]
\]

其中 \(h[i]\) 表示 \(S\) 中模 \(p\) 等于 \(i\) 的元素个数。

〖二〗

设 \(g\) 为模数 \(p\) 的原根,根据原根的性质可知 \(g^1\cdots g^{p-1}\) 互不相同,设 \(f[i][j]\) 表示前 \(i\) 个数的乘积在模 \(p\) 意义下等于 \(g^j\) 的方案数,有

\[f[i][j]=\sum_{k=0}^{p-1}f[i-1][k]\cdot h[j-k]
\]

其中 \(h[i]\) 表示 \(S\) 中模 \(p\) 等于 \(g^i\) 的元素个数。

于是可以化成多项式的形式:

\[(h_0+h_1x+h_2x^2+\cdots+h_{p-1}x^{p-1})^{n-1}
\]

Code

  1. #include <cmath>
  2. #include <cstdio>
  3. #include <algorithm>
  4. const int N = 16390, P = 1004535809, G = 3, Gi = 334845270;
  5. int n, m, x, y, s, g, nn, mm, vis[8002], R[N], h[N], a[N], L, inv;
  6. int read() {
  7. int x = 0; char c = getchar();
  8. while (c < '0' || c > '9') c = getchar();
  9. while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
  10. return x;
  11. }
  12. int ksm(int a, int b, int p) {
  13. int res = 1;
  14. for (; b; b >>= 1, a = 1LL * a * a % p)
  15. if (b & 1) res = 1LL * res * a % p;
  16. return res;
  17. }
  18. int getroot(int x) {
  19. if (x == 2) return 1;
  20. int m = sqrt(x - 1);
  21. for (int i = 2; ; ++i) {
  22. bool ok = 1;
  23. for (int j = 2; j <= m; ++j)
  24. if (ksm(i, (x - 1) / j, x) == 1) { ok = 0; break; }
  25. if (ok) return i;
  26. }
  27. }
  28. void NTT(int *A, int f) {
  29. for (int i = 0; i < nn; ++i) if (i < R[i]) std::swap(A[i], A[R[i]]);
  30. for (int i = 1; i < nn; i <<= 1) {
  31. int wn = ksm(f == 1 ? G : Gi, (P - 1) / (i << 1), P);
  32. for (int j = 0, r = i << 1; j < nn; j += r) {
  33. int w = 1;
  34. for (int k = 0; k < i; ++k, w = 1LL * w * wn % P) {
  35. int x = A[j + k], y = 1LL * w * A[i + j + k] % P;
  36. A[j + k] = (x + y) % P, A[i + j + k] = (x - y + P) % P;
  37. }
  38. }
  39. }
  40. }
  41. void mul(int *a, int *b) {
  42. int c[N] = {}, d[N] = {};
  43. for (int i = 1; i < m; ++i) c[i] = a[i], d[i] = b[i];
  44. NTT(c, 1), NTT(d, 1);
  45. for (int i = 0; i < nn; ++i) a[i] = 1LL * c[i] * d[i] % P;
  46. NTT(a, -1);
  47. for (int i = 0; i <= mm; ++i) a[i] = 1LL * a[i] * inv % P;
  48. for (int i = m; i <= mm; ++i) {
  49. a[i - m + 1] += a[i];
  50. if (a[i - m + 1] >= P) a[i - m + 1] -= P;
  51. a[i] = 0;
  52. }
  53. }
  54. void fastpow(int b) {
  55. for (; b; b >>= 1, mul(a, a))
  56. if (b & 1) mul(h, a);
  57. }
  58. int main() {
  59. n = read(), m = read(), x = read(), s = read();
  60. g = getroot(m);
  61. for (int i = 1; i <= s; ++i) vis[read()] = 1;
  62. for (int i = 1, t; i < m; ++i) {
  63. t = ksm(g, i, m), h[i] = a[i] = vis[t];
  64. if (x == t) y = i;
  65. }
  66. mm = (m - 1) << 1;
  67. for (nn = 1; nn <= mm; nn <<= 1) ++L;
  68. inv = ksm(nn, P - 2, P);
  69. for (int i = 0; i < nn; ++i) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
  70. fastpow(n - 1);
  71. printf("%d\n", h[y]);
  72. return 0;
  73. }

[BZOJ 3992] [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. [SDOI 2015]序列统计

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

  4. 【BZOJ 4403】 4403: 序列统计 (卢卡斯定理)

    4403: 序列统计 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 653  Solved: 320 Description 给定三个正整数N.L和R, ...

  5. [BZOJ 4818] [SDOI 2017] 序列计数

    Description Alice想要得到一个长度为 \(n\) 的序列,序列中的数都是不超过 \(m\) 的正整数,而且这 \(n\) 个数的和是 \(p\) 的倍数. Alice还希望,这 \(n ...

  6. BZOJ 3990 [SDOI 2015] 排序 解题报告

    这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 ...

  7. BZOJ 3993 [SDOI 2015] 星际战争 解题报告

    首先我们可以二分答案. 假设当前二分出来的答案是 $Ans$ ,那么我们考虑用网络流检验: 设武器为 $X$,第 $i$ 个武器的攻击力为 $B_i$: 设机器人为 $Y$,第 $i$ 个机器人的装甲 ...

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

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

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

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

随机推荐

  1. linux c ---raise 使用范例的代码

    把做工程过程中比较好的代码片段收藏起来,下面代码内容是关于linux c ---raise 使用范例的代码,希望对各位有所用途. #include <sys/types.h> #inclu ...

  2. SpringBoot 配置定时任务

    SpringBoot启用定时任务,其内部集成了成熟的框架,因此我们可以很简单的使用它. 开启定时任务 @SpringBootApplication //设置扫描的组件的包 @ComponentScan ...

  3. idea上使用maven入门(二)——本地仓库以及使用maven

    本地仓库: 首先创建完一个项目之后,点击左上角file->setting(建一个文件夹repository,建议创建到maven的外面,主要如果maven需要换版本,方便管理)如下图: ​ ma ...

  4. DVWA 黑客攻防演练(三)命令行注入(Command Injection)

    文章会讨论 DVWA 中低.中.高.不可能级别的命令行注入 这里的需求是在服务器上可以 ping 一下其他的服务器 低级 Hacker 试下输入 192.168.31.130; cat /etc/ap ...

  5. PJSUA2开发文档--第四章 端点ENDPOINT

    4.端点ENDPOINT Endpoint类是一个单例类,应用程序必须在此类实例之前创建一个并且最多只能创建一个,然后才能执行任何操作.同样,一旦这个类被销毁,应用程序就不能调用该库的任何API.这个 ...

  6. 推荐一款关于MongoDB日志分析的工具--Mtools

    一. 需求背景 MongoDB数据库的强大的文档模型使其成为处理数据的最佳方式.文档适用于广泛的流行数据模型,支持各种各样的场景.文档模型可以包含键值.关系数据集和图形数据集,当然,还可以包含父子关系 ...

  7. power-virus

    http://0cx.cc/category/yunwei/ 介绍安全姿势 https://www.freebuf.com/articles/system/193557.html

  8. Linux内核最新的连续内存分配器(CMA)——避免预留大块内存【转】

    在我们使用ARM等嵌入式Linux系统的时候,一个头疼的问题是GPU,Camera,HDMI等都需要预留大量连续内存,这部分内存平时不用,但是一般的做法又必须先预留着.目前,Marek Szyprow ...

  9. 在windows下搭建汇编编程环境

    汇编语言程序搭建masm+debug 下载链接 dosbox:链接:https://pan.baidu.com/s/1TgkfU-d5w6Nz9TOYro1pYw 密码:mp83 masm:链接:ht ...

  10. A Deep Learning-Based System for Vulnerability Detection

    本篇文献作者提出了一种基于深度学习来检测软件漏洞的方案.       摘要:作者开始基于深度学习的漏洞检测研究,是为了减轻专家手工定义特性的繁琐任务,需要制定一些指导性原则来适用于深度学习去进行漏洞探 ...