ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P7431 [THUPC2017] 小 L 的计算题

2021-04-08 17:01:34  阅读:172  来源: 互联网

标签:THUPC2017 P7431 计算题 int sum Poly len return resize


\[f_k=\sum_{i=1}^n {a_i}^k \]

\[\begin{aligned} F(x)&=\sum_{k \ge 0}x^k\sum_{i=1}^n {a_i}^k \\ &=\sum_{i=1}^n\sum_{k \ge 0}x^k {a_i}^k \\ &= \sum_{i=1}^n\frac{1}{1-a_ix} \\ &=\sum_{i=1}^n \left( 1 - \frac{-a_ix}{1-a_ix} \right) \\ &=n-\sum_{i=1}^n \frac{-a_ix}{1-a_ix} \\ &= n-x\sum_{i=1}^n \ln(1-a_ix)' \\ &= n-x \left( \ln \left( \prod_{i=1}^n 1-a_ix \right)\right)' \end{aligned}\]

分治 fft + 多项式 ln 即可,时间复杂度 \(\mathcal O(n \log^2 n)\)

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;

const int MAXN = 8e6 , Mod = 998244353;
int Add( int x , int y ) { x += y; return x >= Mod ? x - Mod : x; }
int Sub( int x , int y ) { x -= y; return x < 0 ? x + Mod : x; }
int Mul( int x , int y ) { return 1ll * x * y % Mod; }
int Quick_pow( int x , int po ) { int Ans = 1; for( ; po ; po >>= 1 , x = Mul( x , x ) ) if( po & 1 ) Ans = Mul( Ans , x ); return Ans; }
int Inv( int x ) { return Quick_pow( x , Mod - 2 ); }
int iv[ MAXN + 5 ];
void Init() {
	iv[ 1 ] = 1;
	for( int i = 2 ; i <= MAXN ; i ++ ) iv[ i ] = Mul( Mod - Mod / i , iv[ Mod % i ] );
}

#define Poly vector< int >
#define len( x ) ( (int)x.size() )
Poly operator - ( int x , Poly f ) { for( int i = 0 ; i < len( f ) ; i ++ ) f[ i ] = Mod - f[ i ]; f[ 0 ] = Add( f[ 0 ] , x ); return f; }
Poly operator - ( Poly f , int x ) { f[ 0 ] = Sub( f[ 0 ] , x ); return f; }
Poly operator * ( Poly f , int x ) { for( int i = 0 ; i < len( f ) ; i ++ ) f[ i ] = Mul( f[ i ] , x ); return f; }
Poly operator + ( Poly f , Poly g ) {
	int n = max( len( f ) , len( g ) ); f.resize( n ); g.resize( n );
	for( int i = 0 ; i < n ; i ++ ) f[ i ] = Add( f[ i ] , g[ i ] );
	return f;
}
Poly operator - ( Poly f , Poly g ) {
	int n = max( len( f ) , len( g ) ); f.resize( n ); g.resize( n );
	for( int i = 0 ; i < n ; i ++ ) f[ i ] = Sub( f[ i ] , g[ i ] );
	return f;
}

const int G = 3 , IG = 332748118;
int lim , ilim , rev[ MAXN + 5 ];
void ntt( Poly &f , int op ) {
	for( int i = 0 ; i < lim ; i ++ ) if( i < rev[ i ] ) swap( f[ i ] , f[ rev[ i ] ] );
	for( int len = 2 , w ; len <= lim ; len <<= 1 ) {
		w = Quick_pow( op == 1 ? G : IG , ( Mod - 1 ) / len );
		for( int l = 0 ; l < lim ; l += len ) {
			for( int i = l , wk = 1 ; i < l + len / 2 ; i ++ , wk = Mul( wk , w ) ) {
				int t = Mul( wk , f[ i + len / 2 ] );
				f[ i + len / 2 ] = Sub( f[ i ] , t ); f[ i ] = Add( f[ i ] , t );
			}
		}
	}
	if( op == -1 ) for( int i = 0 ; i < lim ; i ++ ) f[ i ] = Mul( f[ i ] , ilim );
}
int mxlen = 100000000;
Poly operator * ( Poly f , Poly g ) {
	int n = len( f ) + len( g ) - 1; for( lim = 1 ; lim < n ; lim <<= 1 ); ilim = Inv( lim );
	for( int i = 0 ; i < lim ; i ++ ) rev[ i ] = ( rev[ i >> 1 ] >> 1 ) | ( i & 1 ? lim >> 1 : 0 );
	f.resize( lim ); g.resize( lim );
	ntt( f , 1 ); ntt( g , 1 );
	for( int i = 0 ; i < lim ; i ++ ) f[ i ] = Mul( f[ i ] , g[ i ] );
	ntt( f , -1 ); f.resize( min( n , mxlen ) );
	return f;
}
Poly Inv( Poly f ) {
	Poly g = Poly( 1 , Inv( f[ 0 ] ) );
	for( mxlen = 2 ; mxlen < 2 * len( f ) ; mxlen <<= 1 ) {
		Poly A = f; A.resize( mxlen );
		g = g * ( 2 - ( g * A ) ); 
	}
	g.resize( len( f ) ); return g;
}
Poly Der( Poly f ) {
	for( int i = 0 ; i < len( f ) - 1 ; i ++ ) f[ i ] = Mul( i + 1 , f[ i + 1 ] );
	f.resize( len( f ) - 1 );
	return f;
}
Poly Int( Poly f ) {
	f.resize( len( f ) + 1 );
	for( int i = len( f ) - 1 ; i >= 1 ; i -- ) f[ i ] = Mul( f[ i - 1 ] , iv[ i ] );
	f[ 0 ] = 0;
	return f;
}
Poly Ln( Poly f ) {
	Poly g = Int( Der( f ) * Inv( f ) );
	g.resize( len( f ) ); return g;
}
Poly Exp( Poly f ) {
	Poly g = Poly( 1 , 1 );
	for( mxlen = 2 ; mxlen < 4 * len( f ) ; mxlen <<= 1 ) {
		Poly A = f; A.resize( mxlen );
		g = g * ( ( 1 - Ln( g ) ) + A );
	}
	g.resize( len( f ) ); return g;
}
Poly Pow( Poly f , int k ) {
	f = Ln( f ); f = f * k; f = Exp( f );
	return f;
}
Poly Sqrt( Poly f ) {
	Poly g = Poly( 1 , 1 );
	for( mxlen = 2 ; mxlen < 4 * len( f ) ; mxlen <<= 1 ) {
		Poly A = f; A.resize( mxlen );
		g = ( g + ( A * Inv( g ) ) ) * Inv( 2 );
	}
	g.resize( len( f ) ); return g;
}

int T , n; Poly f[ MAXN + 5 ] , g;

Poly cdq_ntt( int l , int r ) {
	if( l == r ) return f[ l ];
	return cdq_ntt( l , ( l + r ) / 2 ) * cdq_ntt( ( l + r ) / 2 + 1 , r );
}

signed main( ) {
	Init();
	scanf("%d",&T);
	while( T -- ) {
		scanf("%d",&n);
		for( int i = 1 , a ; i <= n ; i ++ ) {
			scanf("%d",&a); f[ i ].resize( 2 );
			f[ i ][ 0 ] = 1 , f[ i ][ 1 ] = Mod - a;
		}
		g = Der( Ln( cdq_ntt( 1 , n ) ) );
		g.resize( len( g ) + 1 ); 
		for( int i = len( g ) - 1 ; i >= 1 ; i -- ) g[ i ] = g[ i - 1 ]; g[ 0 ] = 0;
		g = n - g;

		int Xor = 0;
		for( int i = 1 ; i <= n ; i ++ ) Xor ^= g[ i ];
		printf("%d\n", Xor );
	}
	return 0;
}

标签:THUPC2017,P7431,计算题,int,sum,Poly,len,return,resize
来源: https://www.cnblogs.com/chihik/p/14633280.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有