多项式模板

模板错的次数太多了,甚至模板题错了都能过。/zk/zk/zk 记录一下

多项式乘法
void ntt ( int *a , int lm ) {
	for ( int i = 1 ; i < lm ; ++ i )
		if ( i < tx [ i ] )
			swap ( a [ i ] , a [ tx [ i ] ] ) ;
	for ( int i = 1 ; i < lm ; i <<= 1 ) {
		int x = qpow ( G , ( M - 1 ) / ( i << 1 ) ) ;
		for ( int j = 0 ; j < lm ; j += ( i << 1 ) ) {
			for ( int k = 0 , y = 1 ; k < i ; ++ k , y = y * x % M ) {
				int p = a [ j + k ] , q = y * a [ j + k + i ] % M ;
				a [ j + k ] = Ct ( p + q ) ;
				a [ j + k + i ] = Cs ( p - q ) ;
			}
		}
	}
}
分治多项式乘法
#include <iostream>
#include <algorithm>
using namespace std ;

#define int long long
inline int read ( ) {
	char ch = getchar ( ) ;
	int x = 0 ;
	while ( ch < '0' || ch > '9' )
		ch = getchar ( ) ;
	while ( ch >= '0' && ch <= '9' )
		x = x * 10 + ch - 48 , ch = getchar ( ) ;
	return x ;
}

const int N = (1<<18) + 5 , M = 998244353 , G = 3 ;
int n , lim , f[N] , g[N] , u[N] , v[N] , tx[N] , lg[N] ;

inline int qpow ( int x , int y ) {
	int res = 1 ;
	while ( y ) {
		if ( y & 1 )
			res = res * x % M ;
		x = x * x % M ;
		y >>= 1 ;
	}
	return res ;
}

int Ct ( int x ) { return x >= M ? x - M : x ; }
int Cs ( int x ) { return x < 0 ? x + M : x ; }

void ntt ( int *a , int lm ) {
	for ( int i = 1 ; i < lm ; ++ i )
		if ( i < tx [ i ] )
			swap ( a [ i ] , a [ tx [ i ] ] ) ;
	for ( int i = 1 ; i < lm ; i <<= 1 ) {
		int x = qpow ( G , ( M - 1 ) / ( i << 1 ) ) ;
		for ( int j = 0 ; j < lm ; j += ( i << 1 ) ) {
			for ( int k = 0 , y = 1 ; k < i ; ++ k , y = y * x % M ) {
				int p = a [ j + k ] , q = y * a [ j + k + i ] % M ;
				a [ j + k ] = Ct ( p + q ) ;
				a [ j + k + i ] = Cs ( p - q ) ;
			}
		}
	}
}

void solve ( int l , int r ) {
	if ( l == r ) {
		if ( l == 0 ) f [ l ] = 1 ;
		return ;
	}
	int mid = ( l + r ) >> 1 ;
	solve ( l , mid ) ;
	int lim = r - l + 1 ;
	for ( int i = l ; i <= r ; ++ i )
		u [ i - l ] = f [ i ] , v [ i - l ] = g [ i - l ] ;
	for ( int i = ( lim >> 1 ) ; i < lim ; ++ i )
		u [ i ] = 0 ;
	for ( int i = lim ; i < ( lim << 1 ) ; ++ i )
		u [ i ] = v [ i ] = 0 ;
	lim <<= 1 ;
	int len = lg [ r - l + 1 ] ;
	for ( int i = 1 ; i < lim ; ++ i )
		tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) << len ) ;
	ntt ( u , lim ) , ntt ( v , lim ) ;
	for ( int i = 0 ; i < lim ; ++ i )
		u [ i ] = u [ i ] * v [ i ] % M ;
	ntt ( u , lim ) ;
	reverse ( u + 1 , u + lim ) ;
	int lv = qpow ( lim , M - 2 ) ;
	lim >>= 1 ;
	for ( int i = ( lim >> 1 ) ; i < lim ; ++ i )
		f [ l + i ] = Ct ( f [ l + i ] + u [ i ] * lv % M ) ;
	solve ( mid + 1 , r ) ;
}

signed main ( ) {
	n = read ( ) ;
	for ( int i = 1 ; i < n ; ++ i )
		g [ i ] = read ( ) ;
	lim = 1 ;
	while ( lim < n ) lim <<= 1 ;
	lg [ 0 ] = -1 ;
	for ( int i = 1 ; i <= lim ; ++ i )
		lg [ i ] = lg [ i >> 1 ] + 1 ;
	solve ( 0 , lim - 1 ) ;
	for ( int i = 0 ; i < n ; ++ i )
		cout << f [ i ] << " " ;
	cout << "\n" ;
	return 0 ;
}
多项式求逆
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std ;

#define int long long

const int N = 400005 , M = 998244353 , G = 3 ;

inline int read ( ) {
	char ch = getchar ( ) ;
	int x = 0 ;
	while ( ch < '0' || ch > '9' )
		ch = getchar ( ) ;
	while ( ch >= '0' && ch <= '9' )
		x = x * 10 + ch - 48 , ch = getchar ( ) ;
	return x ;
}

inline int qpow ( int x , int y ) {
	int res = 1 ;
	while ( y ) {
		if ( y & 1 )
			res = res * x % M ;
		x = x * x % M ;
		y >>= 1 ;
	}
	return res ;
}

inline int Ct ( int x ) { return x >= M ? x - M : x ; }
inline int Cs ( int x ) { return x < 0 ? x + M : x ; }

int n , tx[N] , a[N] , b[N] ;

void ntt ( int *a , int lm ) {
	for ( int i = 1 ; i < lm ; ++ i )
		if ( i < tx [ i ] )
			swap ( a [ i ] , a [ tx [ i ] ] ) ;
	for ( int i = 1 ; i < lm ; i <<= 1 ) {
		int x = qpow ( G , ( M - 1 ) / ( i << 1 ) ) ;
		for ( int j = 0 ; j < lm ; j += ( i << 1 ) ) {
			for ( int k = 0 , y = 1 ; k < i ; ++ k , y = y * x % M ) {
				int p = a [ j + k ] , q = y * a [ j + k + i ] % M ;
				a [ j + k ] = Ct ( p + q ) ;
				a [ j + k + i ] = Cs ( p - q ) ;
			}
		}
	}
}

void Inv ( int *a , int *b , int n ) {
	static int c[N] ;
	memset ( c , 0 , sizeof ( c ) ) ;
	b [ 0 ] = qpow ( a [ 0 ] , M - 2 ) ;
	int len , lm ;
	for ( len = 2 ; len <= n ; len <<= 1 ) {
		lm = len << 1 ;
		for ( int i = 0 ; i < len ; ++ i )
			c [ i ] = a [ i ] ;
		
		for ( int i = 1 ; i < lm ; ++ i )
			tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) ? len : 0 ) ;
		
		ntt ( c , lm ) , ntt ( b , lm ) ;
		for ( int i = 0 ; i < lm ; ++ i )
			b [ i ] = Cs ( 2 - b [ i ] * c [ i ] % M ) * b [ i ] % M ;
		ntt ( b , lm ) ;
		reverse ( b + 1 , b + lm ) ;
		int lv = qpow ( lm , M - 2 ) ;
		for ( int i = 0 ; i < len ; ++ i )
			b [ i ] = b [ i ] * lv % M ;
		for ( int i = len ; i < lm ; ++ i )
			b [ i ] = 0 ;
	}
	for ( int i = n ; i < len ; ++ i )
		b [ i ] = 0 ;
}

signed main ( ) {
	n = read ( ) ;
	for ( int i = 0 ; i < n ; ++ i )
		a [ i ] = read ( ) ;
	int lim = 1 ;
	while ( lim <= n ) lim <<= 1 ;
	Inv ( a , b , lim ) ;
	for ( int i = 0 ; i < n ; ++ i )
		cout << b [ i ] << " " ;
	cout << "\n" ;
	return 0 ;
}
多项式Ln
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std ;

#define int long long
const int N = 400005 , M = 998244353 , G = 3 ;

inline int read ( ) {
	char ch = getchar ( ) ;
	int x = 0 ;
	while ( ch < '0' || ch > '9' )
		ch = getchar ( ) ;
	while ( ch >= '0' && ch <= '9' )
		x = x * 10 + ch - 48 , ch = getchar ( ) ;
	return x ;
}

inline int qpow ( int x , int y ) {
	int res = 1 ;
	while ( y ) {
		if ( y & 1 )
			res = res * x % M ;
		x = x * x % M ;
		y >>= 1 ;
	}
	return res ;
}

inline int Ct ( int x ) { return x >= M ? x - M : x ; }
inline int Cs ( int x ) { return x < 0 ? x + M : x ; }

int n , tx[N] , a[N] , b[N] , A[N] ;

void ntt ( int *a , int lm ) {
	for ( int i = 1 ; i < lm ; ++ i )
		if ( i < tx [ i ] )
			swap ( a [ i ] , a [ tx [ i ] ] ) ;
	for ( int i = 1 ; i < lm ; i <<= 1 ) {
		int x = qpow ( G , ( M - 1 ) / ( i << 1 ) ) ;
		for ( int j = 0 ; j < lm ; j += ( i << 1 ) ) {
			for ( int k = 0 , y = 1 ; k < i ; ++ k , y = y * x % M ) {
				int p = a [ j + k ] , q = y * a [ j + k + i ] % M ;
				a [ j + k ] = Ct ( p + q ) ;
				a [ j + k + i ] = Cs ( p - q ) ;
			}
		}
	}
}

void Inv ( int *a , int *b , int n ) {
	static int c[N] ;
	memset ( c , 0 , sizeof ( c ) ) ;
	b [ 0 ] = qpow ( a [ 0 ] , M - 2 ) ;
	int len , lm ;
	for ( len = 2 ; len <= n ; len <<= 1 ) {
		lm = len << 1 ;
		for ( int i = 0 ; i < len ; ++ i )
			c [ i ] = a [ i ] ;
		
		for ( int i = 1 ; i < lm ; ++ i )
			tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) ? len : 0 ) ;
		
		ntt ( c , lm ) , ntt ( b , lm ) ;
		for ( int i = 0 ; i < lm ; ++ i )
			b [ i ] = Cs ( 2 - b [ i ] * c [ i ] % M ) * b [ i ] % M ;
		ntt ( b , lm ) ;
		reverse ( b + 1 , b + lm ) ;
		int lv = qpow ( lm , M - 2 ) ;
		for ( int i = 0 ; i < len ; ++ i )
			b [ i ] = b [ i ] * lv % M ;
		for ( int i = len ; i < lm ; ++ i )
			b [ i ] = 0 ;
	}
	for ( int i = n ; i < len ; ++ i )
		b [ i ] = 0 ;
}

void Deri ( int *a , int lm ) {
	for ( int i = 0 ; i < lm - 1 ; ++ i )
		a [ i ] = a [ i + 1 ] * ( i + 1 ) % M ;
	a [ lm - 1 ] = 0 ;
}

void Inte ( int *a , int lm ) {
	for ( int i = lm - 1 ; i > 0 ; -- i )
		a [ i ] = a [ i - 1 ] * qpow ( i , M - 2 ) % M ;
	a [ 0 ] = 0 ;
}

signed main ( ) {
	n = read ( ) ;
	for ( int i = 0 ; i < n ; ++ i )
		b [ i ] = A [ i ] = read ( ) ;
	
	int len = 1 ;
	while ( len <= n ) len <<= 1 ;
	int lm = len << 1 ;
	
	Deri ( b , len ) ;
	Inv ( A , a , len ) ;
	
	for ( int i = 1 ; i < lm ; ++ i )
		tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) ? len : 0 ) ;
	ntt ( a , lm ) , ntt ( b , lm ) ;
	for ( int i = 0 ; i < lm ; ++ i )
		a [ i ] = a [ i ] * b [ i ] % M ;
	ntt ( a , lm ) ;
	reverse ( a + 1 , a + lm ) ;
	int lv = qpow ( lm , M - 2 ) ;
	for ( int i = 0 ; i < lm ; ++ i )
		a [ i ] = a [ i ] * lv % M ;
	
	Inte ( a , lm ) ;
	for ( int i = 0 ; i < n ; ++ i )
		cout << a [ i ] << " " ;
	cout << "\n" ;
	return 0 ;
}
多项式Exp
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std ;

#define int long long
const int N = 400005 , M = 998244353 , G = 3 ;

inline int read ( ) {
	char ch = getchar ( ) ;
	int x = 0 ;
	while ( ch < '0' || ch > '9' )
		ch = getchar ( ) ;
	while ( ch >= '0' && ch <= '9' )
		x = x * 10 + ch - 48 , ch = getchar ( ) ;
	return x ;
}

inline int qpow ( int x , int y ) {
	int res = 1 ;
	while ( y ) {
		if ( y & 1 )
			res = res * x % M ;
		x = x * x % M ;
		y >>= 1 ;
	}
	return res ;
}

inline int Ct ( int x ) { return x >= M ? x - M : x ; }
inline int Cs ( int x ) { return x < 0 ? x + M : x ; }

int n , tx[N] , a[N] , b[N] ;

void ntt ( int *a , int lm ) {
	for ( int i = 1 ; i < lm ; ++ i )
		if ( i < tx [ i ] )
			swap ( a [ i ] , a [ tx [ i ] ] ) ;
	for ( int i = 1 ; i < lm ; i <<= 1 ) {
		int x = qpow ( G , ( M - 1 ) / ( i << 1 ) ) ;
		for ( int j = 0 ; j < lm ; j += ( i << 1 ) ) {
			for ( int k = 0 , y = 1 ; k < i ; ++ k , y = y * x % M ) {
				int p = a [ j + k ] , q = y * a [ j + k + i ] % M ;
				a [ j + k ] = Ct ( p + q ) ;
				a [ j + k + i ] = Cs ( p - q ) ;
			}
		}
	}
}

void Inv ( int *a , int *b , int n ) {
	static int c[N] ;
	memset ( c , 0 , sizeof ( c ) ) ;
	b [ 0 ] = qpow ( a [ 0 ] , M - 2 ) ;
	int len , lm ;
	for ( len = 2 ; len <= n ; len <<= 1 ) {
		lm = len << 1 ;
		for ( int i = 0 ; i < len ; ++ i )
			c [ i ] = a [ i ] ;
		for ( int i = 1 ; i < lm ; ++ i )
			tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) ? len : 0 ) ;
		
		ntt ( c , lm ) , ntt ( b , lm ) ;
		for ( int i = 0 ; i < lm ; ++ i )
			b [ i ] = Cs ( 2 - b [ i ] * c [ i ] % M ) * b [ i ] % M ;
		ntt ( b , lm ) ;
		reverse ( b + 1 , b + lm ) ;
		int lv = qpow ( lm , M - 2 ) ;
		for ( int i = 0 ; i < len ; ++ i )
			b [ i ] = b [ i ] * lv % M ;
		for ( int i = len ; i < lm ; ++ i )
			b [ i ] = 0 ;
	}
	for ( int i = n ; i < len ; ++ i )
		b [ i ] = 0 ;
}

void Deci ( int *a , int lm ) {
	for ( int i = 0 ; i < lm - 1 ; ++ i )
		a [ i ] = a [ i + 1 ] * ( i + 1 ) % M ;
	a [ lm - 1 ] = 0 ;
}

void Inte ( int *a , int lm ) {
	for ( int i = lm - 1 ; i ; -- i )
		a [ i ] = a [ i - 1 ] * qpow ( i , M - 2 ) % M ;
	a [ 0 ] = 0 ;
}

void Ln ( int *a , int *b , int n ) {
	static int c[N] ;
	memset ( c , 0 , sizeof ( c ) ) ;
	
	for ( int i = 0 ; i < n ; ++ i )
		c [ i ] = a [ i ] ;
	Deci ( c , n ) ;
	Inv ( a , b , n ) ;
	
	int lm = n << 1 ;
	for ( int i = 1 ; i < lm ; ++ i )
		tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) ? n : 0 ) ;
	
	ntt ( c , lm ) , ntt ( b , lm ) ;
	for ( int i = 0 ; i < lm ; ++ i )
		b [ i ] = c [ i ] * b [ i ] % M ;
	ntt ( b , lm ) ;
	reverse ( b + 1 , b + lm ) ;
	int lv = qpow ( lm , M - 2 ) ;
	for ( int i = 0 ; i < lm ; ++ i )
		b [ i ] = b [ i ] * lv % M ;
	
	Inte ( b , lm ) ;
	for ( int i = n ; i < lm ; ++ i )
		b [ i ] = 0 ;
}

void Exp ( int *a , int *b , int n ) {
	static int c[N] ;
	b [ 0 ] = 1 ;
	int len , lm ;
	for ( len = 2 ; len <= n ; len <<= 1 ) {
		lm = len << 1 ;
		memset ( c , 0 , sizeof ( c ) ) ;
		
		Ln ( b , c , len ) ;
		for ( int i = 0 ; i < len ; ++ i )
			c [ i ] = Cs ( a [ i ] - c [ i ] ) ;
		c [ 0 ] = Ct ( c [ 0 ] + 1 ) ;
		
		for ( int i = 1 ; i < lm ; ++ i )
			tx [ i ] = ( tx [ i >> 1 ] >> 1 ) | ( ( i & 1 ) ? len : 0 ) ;
		ntt ( c , lm ) , ntt ( b , lm ) ;
		for ( int i = 0 ; i < lm ; ++ i )
			b [ i ] = c [ i ] * b [ i ] % M;
		ntt ( b , lm ) ;
		reverse ( b + 1 , b + lm ) ;
		int lv = qpow ( lm , M - 2 ) ;
		for ( int i = 0 ; i < len ; ++ i )
			b [ i ] = b [ i ] * lv % M ;
		for ( int i = len ; i < lm ; ++ i )
			b [ i ] = 0 ;
	}
	for ( int i = n ; i < len ; ++ i )
		b [ i ] = 0 ;
}

signed main ( ) {
	n = read ( ) ;
	for ( int i = 0 ; i < n ; ++ i )
		a [ i ] = read ( ) ;
	int lm = 1 ;
	while ( lm <= n ) lm <<= 1 ;
	Exp ( a , b , lm ) ;
	for ( int i = 0 ; i < n ; ++ i )
		cout << b [ i ] << " " ;
	cout << "\n" ;
	return 0 ;
}
posted @   灵华  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示