IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【luogu P5273】【模板】多项式幂函数(加强版)(NTT) -> 正文阅读

[C++知识库]【luogu P5273】【模板】多项式幂函数(加强版)(NTT)

【模板】多项式幂函数(加强版)

题目链接:luogu P5273

题目大意

给你一个 n-1 次多项式,要你求它的 k 次方模 x^n 意义下结果。
不保证给出多项式常数项为 1。

思路

我们考虑常数项不是一会怎样。

A k ( x ) = e ln ? ( A ( x ) ) ? k A^k(x)=e^{\ln(A(x))*k} Ak(x)=eln(A(x))?k
会发现问题出在 ln ? ( A ( x ) ) \ln(A(x)) ln(A(x)) 需要常数项是 1 1 1

那不是 1 1 1 咋办?
考虑先除常数项,然后正常算,然后常数项的 k k k 次方算出来,然后再乘回去。
(然后这里要注意一下常数项 k k k 次方这里的 k k k % ( 998244353 ? 1 ) \%(998244353-1) %(998244353?1) 的【欧拉定理】)

然后就可以了?其实会挂,因为常数项可能是 0 0 0
那咋办呢?那就直接找第一个不是 0 0 0 的项,先左移,算出来再右移。

然后你要注意看一下前面 0 0 0 的数量会不会超过 n ? 1 n-1 n?1 次,如果超了就肯定是全 0 0 0
(这里记得你的 k k k 取模了,所以你如果要用取模后的 k k k 你要判断一下 k k k 字符串的长度是否明显大于 n n n

然后就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mo 998244353
#define clr(f, n) memset(f, 0, (n) * sizeof(int))
#define cpy(f, g, n) memcpy(f, g, (n) * sizeof(int))

using namespace std;

const int N = 100000 * 8 + 1;
int n, m, f[N], g[N], an[N], inv[N], G, Gv;
int Gs[N], Gvs[N], Ws[N];
char s[100001];

int jia(int x, int y) {return x + y >= mo ? x + y - mo : x + y;}
int jian(int x, int y) {return x - y < 0 ? x - y + mo : x - y;}
int cheng(int x, int y) {return 1ll * x * y % mo;}
int ksm(int x, int y) {int re = 1; while (y) {if (y & 1) re = cheng(re, x); x = cheng(x, x); y >>= 1;} return re;}

void Init() {
	G = 3; Gv = ksm(G, mo - 2);
	inv[0] = inv[1] = 1; for (int i = 2; i < N; i++) inv[i] = cheng(inv[mo % i], mo - mo / i);
	for (int i = 1; i < N; i <<= 1) {
		Gs[i] = ksm(G, (mo - 1) / (i << 1));
		Gvs[i] = ksm(Gv, (mo - 1) / (i << 1));
	}
}

void get_an(int limit, int l_size) {
	for (int i = 0; i < limit; i++)
		an[i] = (an[i >> 1] >> 1) | ((i & 1) << (l_size - 1)); 
}

void NTT(int *f, int limit, int op) {
	for (int i = 0; i < limit; i++) if (an[i] < i) swap(f[an[i]], f[i]);
	for (int mid = 1; mid < limit; mid <<= 1) {
		//int Wn = ksm(op == 1 ? G : Gv, (mo - 1) / (mid << 1));
		int Wn = (op == 1) ? Gs[mid] : Gvs[mid];
		Ws[0] = 1; for (int i = 1; i < mid; i++) Ws[i] = cheng(Ws[i - 1], Wn);
		for (int R = (mid << 1), j = 0; j < limit; j += R) {
//			int w = 1;
//			for (int k = 0; k < mid; k++, w = cheng(w, Wn)) {
			for (int k = 0; k < mid; k++) {
//				int x = f[j | k], y = cheng(w, f[j | mid | k]);
				int x = f[j | k], y = cheng(Ws[k], f[j | mid | k]);
				f[j | k] = jia(x, y); f[j | mid | k] = jian(x, y);
			}
		}
	}
	if (op == -1) {
		int limv = ksm(limit, mo - 2);
		for (int i = 0; i < limit; i++) f[i] = cheng(f[i], limv);
	}
}

void px(int *f, int *g, int limit) {
	for (int i = 0; i < limit; i++)
		f[i] = cheng(f[i], g[i]);
}

void times(int *f, int *g, int n, int m) {
	static int tmp[N];
	int limit = 1, l_size = 0; while (limit < n + n) limit <<= 1, l_size++;
	cpy(tmp, g, n); clr(tmp + n, limit - n);
	get_an(limit, l_size);
	NTT(f, limit, 1); NTT(tmp, limit, 1);
	px(f, tmp, limit); NTT(f, limit, -1);
	clr(f + m, limit - m); clr(tmp, limit);
}

void invp(int *f, int n) {
	static int w[N], r[N], tmp[N];
	w[0] = ksm(f[0], mo - 2);
	int limit = 1, l_size = 0;
	for (int len = 2; (len >> 1) <= n; len <<= 1) {
		limit = len; l_size++; get_an(limit, l_size);
		cpy(r, w, len >> 1);
		cpy(tmp, f, limit); NTT(tmp, limit, 1);
		NTT(r, limit, 1); px(r, tmp, limit);
		NTT(r, limit, -1); clr(r, limit >> 1);
		cpy(tmp, w, len); NTT(tmp, limit, 1);
		NTT(r, limit, 1); px(r, tmp, limit);
		NTT(r, limit, -1);
		for (int i = (len >> 1); i < len; i++)
			w[i] = jian(cheng(w[i], 2), r[i]);
	}
	cpy(f, w, n); clr(w, limit); clr(r, limit); clr(tmp, limit);
}

void dao(int *f, int n) {
	for (int i = 1; i < n; i++)
		f[i - 1] = cheng(f[i], i);
	f[n - 1] = 0;
}

void jifen(int *f, int n) {
	for (int i = n; i >= 1; i--)
		f[i] = cheng(f[i - 1], inv[i]);
	f[0] = 0;
}

void mof(int *f, int n, int *g, int m) {
	static int f_[N], g_[N];
	int L = n - m + 1;
	reverse(f, f + n); cpy(f_, f, L); reverse(f, f + n); 
	reverse(g, g + m); cpy(g_ , g, L); reverse(g, g + m);
	invp(g_, L); times(g_, f_, L, L); reverse(g_, g_ + L);
	
	times(g, g_, n, n);
	for (int i = 0; i < m - 1; i++) g[i] = jian(f[i], g[i]);
	clr(g + m - 1, L);
	cpy(f, g_, L); clr(f + L, n - L);
}

void lnp(int *f, int n) {
	static int g[N];
	cpy(g, f, n); dao(g, n);
	invp(f, n); times(f, g, n, n);
	jifen(f, n - 1); clr(g, n);
}

void exp(int *f, int n) {
	static int w[N], ww[N];
	ww[0] = 1;
	int len;
	for (len = 2; (len >> 1) <= n; len <<= 1) {
		cpy(w, ww, len >> 1); lnp(w, len);
		for (int i = 0; i < len; i++)
			w[i] = jian(f[i], w[i]);
		w[0] = jia(w[0], 1);
		times(ww, w, len, len);
	}
	len >>= 1;
	cpy(f, ww, n); clr(ww, len); clr(w, len);
}

void ksmp(int *f, int n, int k) {
	lnp(f, n);
	for (int i = 0; i < n; i++) f[i] = cheng(f[i], k);
	exp(f, n);
}

void ksmp_ex(int *f, int n, int k, int kk) {
	int di = 0, c;
	while (!f[di]) di++; c = ksm(f[di], mo - 2);
	if (di && (strlen(s + 1) > 5 || 1ll * di * k >= n)) {
		clr(f, n); return ;
	}
	n -= di * k;
	for (int i = 0; i < n; i++) f[i] = cheng(f[i + di], c);
	clr(f + n, di * k); ksmp(f, n, k);
	c = ksm(c, mo - 2); c = ksm(c, kk);
	static int g[N];
	for (int i = 0; i < n; i++) g[di * k + i] = cheng(f[i], c);
	cpy(f, g, di * k + n); clr(g, di * k + n);
}

int main() {
	Init();
	
	scanf("%d %s", &n, s + 1);
	for (int i = 0; i < n; i++) scanf("%d", &f[i]);
	
	int k = 0, kk = 0, sn = strlen(s + 1);
	for (int i = 1; i <= sn; i++) k = jia(cheng(k, 10), s[i] - '0');
	for (int i = 1; i <= sn; i++) kk = (1ll * kk * 10 + s[i] - '0') % (mo - 1);
	
	ksmp_ex(f, n, k, kk);
	
	for (int i = 0; i < n; i++) printf("%d ", f[i]);
	
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:13:21  更:2022-03-15 22:13:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:26:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码