[洛谷P3321][SDOI2015]序列统计

摘要:
给你一个集合$n,m,x,S(S_iin(0,m),mleqslat8000,minm{prime},nleqslat10^9)$,找到一个长度为$n$的序列$Q$,满足$Q_IinS$和$prodlimits_{i=1}^nQ_i=x$,这是计算序列数问题的解决方案:乘法很麻烦。您可以为每个数字计算$ln$,并且可以获得$m$的原始根。原始根可以通过$O(m^2)$计算,然后每个数字可以通过$ln$计算,生成函数$F(x)$可以计算,$F^n(x)$可以计算。发现$n$很大,多项式可以提高到快次方。

题目大意:给你一个集合$n,m,x,S(S_iin(0,m],mleqslant 8000,min m{prime},nleqslant10^9)$,求一个长度为$n$的序列$Q$,满足$Q_iin S$,且$prodlimits _{i=1}^nQ_i=x$,求序列的个数

题解:乘比较麻烦,可以把每个数求$ln$,可以求出$m$的原根,求原根可以暴力$O(m^2)$求,然后每个数求$ln$,求出生成函数$F(x)$,算出$F^n(x)$。发现$n$较大,多项式快速幂即可。

卡点:

C++ Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 16384 | 3
#define maxm 8010
const int mod = 1004535809, G = 3;
int n, m, x, S, g;
int vis[maxm];
int get(int m) {
	bool find = false;
	for (int i = 2; i < m; i++) {
		memset(vis, -1, sizeof vis);
		int t = 1;
		vis[1] = 0;
		for (int j = 1; j < m - 1; j++) {
			t = t * i % m;
			if (~vis[t]) break;
			else vis[t] = j;
			if (j == m - 2) find = true;
		}
		if (find) return i;
	}
	return 20040826;
}
int lim, ilim, s, rev[maxn];
int base[maxn], ans[maxn], Wn[maxn + 1];
inline int pw(int base, int p) {
	int res = 1;
	for (; p; p >>= 1, base = 1ll * base * base % mod) if (p & 1) res = 1ll * res * base % mod;
	return res;
}
inline int Inv(int x) {return pw(x, mod - 2);}
inline void init(int n) {
	lim = 1, s = -1; while (lim < n) lim <<= 1, s++; ilim = Inv(lim);
	for (int i = 0; i < lim; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
	int t = pw(G, (mod - 1) / lim);
	Wn[0] = 1; for (int i = 1; i <= lim; i++) Wn[i] = 1ll * Wn[i - 1] * t % mod;
}
inline void up(int &a, int b) {if ((a += b) >= mod) a -= mod;}
inline void NTT(int *A, int op) {
	for (int i = 0; i < lim; i++) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
	for (int mid = 1; mid < lim; mid <<= 1) {
		int t = lim / mid >> 1;
		for (int i = 0; i < lim; i += mid << 1) {
			for (int j = 0; j < mid; j++) {
				int W = op ? Wn[j * t] : Wn[lim - j * t];
				int X = A[i + j], Y = 1ll * A[i + j + mid] * W % mod;
				up(A[i + j], Y), up(A[i + j + mid] = X, mod - Y);
			}
		}
	}
	if (!op) for (int i = 0; i < lim; i++) A[i] = 1ll * A[i] * ilim % mod;
}
int C[maxn], D[maxn];
inline void MUL(int *A, int *B) {
	for (int i = 0; i < lim; i++) C[i] = A[i], D[i] = B[i];
	NTT(C, 1), NTT(D, 1);
	for (int i = 0; i < lim; i++) C[i] = 1ll * C[i] * D[i] % mod;
	NTT(C, 0);
	for (int i = 0; i < lim; i++) A[i] = C[i];
	for (int i = m - 1; i < lim; i++) (A[i % (m - 1)] += A[i]) %= mod, A[i] = 0;
}
int main() {
	scanf("%d%d%d%d", &n, &m, &x, &S);
	g = get(m);
	for (int i = 0, tmp; i < S; i++) {
		scanf("%d", &tmp);
		if (tmp) base[vis[tmp]] = 1;
	}
	init(m << 1);
	ans[0] = 1;
	for (; n; n >>= 1, MUL(base, base)) if (n & 1) MUL(ans, base);
	printf("%d
", ans[vis[x]]);
	return 0;
}

  

免责声明:文章转载自《[洛谷P3321][SDOI2015]序列统计》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[NewLife.XCode]导入导出(实体对象百变魔君)pub/sub的实际应用总结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

pip 安装

一、说明 CentOS6.5自带python环境为2.6,公司的python环境为2.7. 为了避免出现以后代码出现版本差异,所以把自带的2 .6版本升级到了2.7,过程十分曲折。。。。 中途遇到的问题和解决方法请点击:Python安装时遇到的问题 二、安装步骤 1、下载安装包 官方下载地址为:https://www.python.org/download...

解决 ln -s 软链接产生的Too many levels of symbolic links错误

参考: ln -s 软链接产生Too many levels of symbolic links错误 解决 ln -s 软链接产生的Too many levels of symbolic links错误 解决方法:在使用ln -s命令时,使用绝对路径取代相对路径,例如: ln -s /home/sdn/cmake/bin/cmake /usr/bin/cm...

df/du、swap、quota、ln

1.vmware分配新磁盘,并格式化挂载 关闭虚拟机 -> 编辑虚拟机设置 -> 硬盘 -> 添加 -> 硬盘 -> SCSI(S) -> 创建新虚拟磁盘 -> 设置大小,将虚拟磁盘拆分成为多个文件 -> 设置文件名 -> 确定 -> 开启虚拟机 通过ls /dev/可以看到,sda盘被分成了sd...

linux随笔:安装软连接时:ln: failed to create symbolic link ‘/usr/bin/python3/python3’: File exists

在云服务上面安装python: 1.安装软连接时报:ln: failed to create symbolic link ‘/usr/bin/python3/python3’: File exists 2.解决方法:删除软连接 rm /usr/bin/python3 重新安装软连接:ln -s /root/python36/bin/python3 /usr...