首页 > 其他分享 >多项式封装

多项式封装

时间:2023-01-04 15:22:29浏览次数:32  
标签:封装 int 多项式 ll poly return MOD deg

推销一下基于继承的多项式封装,好多函数可以直接用vector的,不用再次封装了,省事很多
另外()运算符太赞了,虽然时间是resize()的\(4\)倍,但是很好用!!,再也不用费力计算多项式的大小了!!!

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;
const int N = 4e5+10;
int rev[N];
ll qpow(ll a, ll b){
	ll ret = 1;
	for(; b ; b >>= 1){
		if(b & 1) ret = ret *a % MOD;
		a = a * a % MOD;
	}
	return ret;
}
ll ginv(ll x){
	return qpow(x, MOD - 2);
}
ll add(ll x, ll y){
	x += y;
	if(x >= MOD) return x - MOD;
	return x;
}
ll sub(ll x, ll y){
	x -= y;
	if(x < 0) return x + MOD;
	return x;
}
ll w[N];
int preNTT(int len){
	int deg = 1;
	while(deg < len) deg *= 2;
	for(int i = 0; i < deg; ++i)
		rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? deg / 2 : 0);
	w[0] = 1;
	w[1] = qpow(3, (MOD - 1) / deg);
	for(int i = 2; i < deg; ++i) w[i] = w[i - 1] * w[1]% MOD;
	return deg;
}
struct poly : vector<ll>{
	using vector ::vector;
	using vector :: operator [];
	void cksize(int x){
		if(size() < x) resize(x);
	}
	ll& operator ()(int x){
		cksize(x + 1);
		return this->operator[](x);
	}
	friend poly diff(poly f){
		for(int i = 0; i + 1 < f.size(); ++i){
			f[i] = f[i + 1] * (i + 1) % MOD;
		}
		f.pop_back();
		return f;
	}
	friend poly inte(poly f){
		for(int i = int(f.size()) - 1; i >= 1; --i){
			f[i] = f[i - 1] * ginv(i) % MOD;
		}
		f[0] = 0;
		return f;
	}
	void makemod(){
		for(auto & it : (*this)){
			it = (it % MOD+ MOD) % MOD;
		}
	}
	friend void NTT(poly &f, int deg, int opt){
		f.resize(deg);
		// f.ckmod();
		for(int i = 0; i < deg; ++i){
			if(i < rev[i]) std::swap(f[i], f[rev[i]]);
		}
		for(int h = 2, m = 1, t = deg / 2; h <= deg; h *= 2, m *= 2, t /= 2){
			for(int l = 0; l < deg; l += h){
				for(int i = l, j = 0; i < l + m; ++j,++i){
					ll x = f[i], y = w[t * j] * f[i + m] % MOD;
					f[i] = add(x, y);
					f[i + m] = sub(x, y);
				}
			}
		}
		f.makemod();
		if(opt == -1){
			reverse(f.begin() + 1, f.end());
			ll iv = ginv(deg);
			for(auto &it : f){
				it = it * iv % MOD;
			}
		}
	}
	friend poly dmul(poly f,const poly& g){
		f.cksize(g.size());
		for(int i = 0; i < g.size(); ++i){
			f[i] = f[i] * g[i] % MOD;
		}
		return f;
	}
	friend poly operator - (poly f, const poly& g){
		f.cksize(g.size());
		for(int i = 0; i < g.size(); ++i){
			f[i] = (f[i] - g[i] + MOD) % MOD;
		}
		return f;
	}
	friend poly operator *(poly f, poly g){
		if(f.empty()|| g.empty()) return {};
		int len = f.size() + g.size() - 1;
		int deg = preNTT(len);
		NTT(f, deg, 1);
		NTT(g, deg, 1);
		f = dmul(std::move(f), g);
		NTT(f, deg, -1);
		f.resize(len);
		return f;
	}
	friend poly pinv(const poly& f){
		if(f.empty()) return {};
		poly ret;
		ret(0) = ginv(f[0]);
		poly a;
		for(int len = 2; len < (2 * f.size()); len *= 2){
			a.assign(f.begin(), f.begin() + min(len, (int)f.size()));
			ret.resize(min(len, (int)(f.size())));
			int deg = preNTT(a.size() + ret.size() - 1);
			NTT(ret, deg, 1);
			NTT(a, deg, 1);
			for(int i = 0; i < deg; ++i)
				ret[i] = (2 - a[i] * ret[i] % MOD) * ret[i] % MOD;
			ret.makemod();
			NTT(ret, deg, -1);
			ret.resize(len);
		}
		ret.resize(f.size());
		return ret;
	}
	friend poly sqrt(const poly& f){
		poly res;
		res(0) = 1;
		poly a;
		ll iv2 = ginv(2);
		for(int len = 2; len < 2 * f.size(); len *= 2){
			res.resize(len);
			a.assign(f.begin(), f.begin() + min(len, (int)f.size()));
			a = a * pinv(res);
			for(int i = 0; i < len; ++i) res[i] = (res[i] + a[i]) * iv2 % MOD;
		}
		res.resize(f.size());
		return res;
	}
	friend poly ln(const poly& f){
		poly res = inte(diff(f) * pinv(f));
		res.resize(f.size());
		return res;
	}
	friend poly exp(const poly& f){
		poly ret;
		ret(0) = 1;
		poly a, b;
		for(int len = 2; len < f.size() * 2; len *= 2){
			ret.resize(len);
			a = ln(ret);
			b.assign(f.begin(), f.begin() + min(len, (int)f.size()));
			b = b - a;
			b[0] ++ ;
			ret = ret * b;
			ret.resize(len);
		}
		ret.resize(f.size());
		return ret;
	}
}f;	
int read(){
	int x = 0;
	char ch = getchar();
	while(!isdigit(ch)) ch = getchar();
	while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
	return x;
}
int main(){
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	f.resize(n);
	for(int i = 0; i < n; ++i){
		cin >> f[i];
	}
	f = exp(f);
	for(int i = 0; i < n; ++i){
		cout << f[i] <<" ";
	}
	cout <<endl;
	return 0;
}

标签:封装,int,多项式,ll,poly,return,MOD,deg
From: https://www.cnblogs.com/cdsidi/p/17024940.html

相关文章

  • winform中的提示框+MSN提示封装,原生的也不错
    开发winform项目时,如果某个功能执行完成,需要告诉用户结果,比如成功还是失败?可以用提示框实现,今天就来聊聊这个不太起眼的小功能:提示框。其实net提供的提示框已经很丰富了,如......
  • Cadence Allegro贴片和插件元器件封装制作流程总结
    目录​​1.0805电阻封装的制作​​​​1.1计算焊盘尺寸​​​​1.2制作焊盘(用于生成*.pad)​​​​1.2封装制作(生成*.dra)​​​​1.3设置参数、栅格grid和原点​​​......
  • Java【封装一个新闻类,包含标题和内容属性】
    题目:1、封装一个新闻类,包含标题和内容属性,提供get、set方法,重写toString方法,打印对象时只打印标题;(10分)2、只提供一个带参数的构造器,实例化对象时,只初始化标题;并且实例化......
  • 软件开发入门教程网 之​​数据封装
    所有的C++程序都有以下两个基本要素:**程序语句(代码):**这是程序中执行动作的部分,它们被称为函数。**程序数据:**数据是程序的信息,会受到程序函数的影响。封装是面向对象编程......
  • vue 全局组件封装
    vue中写好一个组件功能<template><divid="app"><divclass="popwin"><pclass="info">{{info}}</p><buttonclass="close_popwin"@cli......
  • python + appium 常用公共方法封装
    appium程序下载安装见之前的帖子:https://www.cnblogs.com/gancuimian/p/16536322.htmlappium环境搭建见之前的帖子:https://www.cnblogs.com/gancuimian/p/16557576.html......
  • cereas学习(2) 鲍威尔函数 多项式
      structF4{template<typenameT>booloperator()(constT*constx1,constT*constx4,T*residual)const{//f4=sqrt(10)(x1-x4)^2r......
  • 封装.继承。多态
    封装高内聚,低耦合,程序设计追求封装,将数据隐藏,设置接口进行交互,就是属性私有privatepackageoop.demo;publicclassStudent{privateintid;privateint......
  • Python类的封装教程
    一、什么是封装封装的本身意思其实就和闭包函数一样,就是把一个函数和变量全都包在一起,但其实这样的说法不是很具体,就是一种很片面的解释二、为什么要封装封装数据的主要......
  • 多项式乘法学习笔记
    多项式乘法给定两个多项式\(A(x)=\sum_{i=0}^{n-1}{a_ix^i}\)\(B(x)=\sum^{m-1}_{i=0}{b_ix^i}\)求\(C(x)=A(x)\timesB(x)=\sum_{i=0}^{n+m-1}{c_ix^i}\)......