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

#include <cmath>
#include <cstdio>
#include <algorithm> const int N = 16390, P = 1004535809, G = 3, Gi = 334845270;
int n, m, x, y, s, g, nn, mm, vis[8002], R[N], h[N], a[N], L, inv; int read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x;
}
int ksm(int a, int b, int p) {
int res = 1;
for (; b; b >>= 1, a = 1LL * a * a % p)
if (b & 1) res = 1LL * res * a % p;
return res;
}
int getroot(int x) {
if (x == 2) return 1;
int m = sqrt(x - 1);
for (int i = 2; ; ++i) {
bool ok = 1;
for (int j = 2; j <= m; ++j)
if (ksm(i, (x - 1) / j, x) == 1) { ok = 0; break; }
if (ok) return i;
}
}
void NTT(int *A, int f) {
for (int i = 0; i < nn; ++i) if (i < R[i]) std::swap(A[i], A[R[i]]);
for (int i = 1; i < nn; i <<= 1) {
int wn = ksm(f == 1 ? G : Gi, (P - 1) / (i << 1), P);
for (int j = 0, r = i << 1; j < nn; j += r) {
int w = 1;
for (int k = 0; k < i; ++k, w = 1LL * w * wn % P) {
int x = A[j + k], y = 1LL * w * A[i + j + k] % P;
A[j + k] = (x + y) % P, A[i + j + k] = (x - y + P) % P;
}
}
}
}
void mul(int *a, int *b) {
int c[N] = {}, d[N] = {};
for (int i = 1; i < m; ++i) c[i] = a[i], d[i] = b[i];
NTT(c, 1), NTT(d, 1);
for (int i = 0; i < nn; ++i) a[i] = 1LL * c[i] * d[i] % P;
NTT(a, -1);
for (int i = 0; i <= mm; ++i) a[i] = 1LL * a[i] * inv % P;
for (int i = m; i <= mm; ++i) {
a[i - m + 1] += a[i];
if (a[i - m + 1] >= P) a[i - m + 1] -= P;
a[i] = 0;
}
}
void fastpow(int b) {
for (; b; b >>= 1, mul(a, a))
if (b & 1) mul(h, a);
}
int main() {
n = read(), m = read(), x = read(), s = read();
g = getroot(m);
for (int i = 1; i <= s; ++i) vis[read()] = 1;
for (int i = 1, t; i < m; ++i) {
t = ksm(g, i, m), h[i] = a[i] = vis[t];
if (x == t) y = i;
}
mm = (m - 1) << 1;
for (nn = 1; nn <= mm; nn <<= 1) ++L;
inv = ksm(nn, P - 2, P);
for (int i = 0; i < nn; ++i) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
fastpow(n - 1);
printf("%d\n", h[y]);
return 0;
}

最新文章

  1. 【开源】知乎日报UWP 更新
  2. unity3d UGUI多语言
  3. C#中调用user32.dll库的keybd_Event函数,操作键盘
  4. C# 文件操作 把文件读取到字节数组
  5. 解决本地tomcat服务器内存不足问题
  6. weblogic性能调优参考
  7. nginx软负载的搭建
  8. Java Web系统经常使用的第三方接口
  9. 0703-APP-Notification-statue-bar
  10. c# 值传递 引用传递
  11. CentOS6.5 --安装orale 11g(上)
  12. Android 利用摄像头指尖测试心率
  13. 带参数的存储过程和标量Function
  14. kotlin成长之路
  15. python利用urllib实现的爬取京东网站商品图片的爬虫
  16. Java之多态
  17. 在64位系统下,指向int型的指针占的内存空间多大?
  18. 01-Git简介和仓库创建
  19. DataTable2JSON 和 DataTable2Class 性能比较
  20. Ubuntu 安装网卡驱动

热门文章

  1. CSS宽高背景介绍
  2. 从零学习Fluter(四):Flutter中ListView组件系列详展
  3. TortoiseSVN 安装时出现 please install the universal crt
  4. jsp用el表达式获取后台传来的值,或者获取session中的值
  5. Python第三天 序列 5种数据类型 数值 字符串 列表 元组 字典 各种数据类型的的xx重写xx表达式
  6. Class.isAssignableFrom与instanceof的区别
  7. XPath Helper的安装与使用
  8. Python面试笔记四
  9. 利用java实现excel转pdf文件
  10. 英语口语练习系列-C05-水电