QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#73168#4384. WalkpoiTL 0ms0kbC++5.0kb2023-01-22 16:56:262023-01-22 16:56:29

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-01-22 16:56:29]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:0kb
  • [2023-01-22 16:56:26]
  • 提交

answer

#include "iostream"
#include "cstring"
#include "cstdio"
#include "algorithm"
#include "queue"
#include "vector"
#include "queue"
#include "stack"
#include "ctime"
#include "set"
#include "map"
#include "cmath"
using namespace std;
#define fi first
#define se second
#define vi vector<int>
#define pb push_back
#define eb emplace_back
#define pii pair<int,int>
#define mp make_pair
#define rep( i , a , b ) for( int i = (a) , i##end = b ; i <= i##end ; ++ i )
#define per( i , a , b ) for( int i = (a) , i##end = b ; i >= i##end ; -- i )
#define mem( a ) memset( a , 0 , sizeof (a) )
#define all( x ) x.begin() , x.end()
//#define int long long
typedef long long ll;
const int MAXN = 5e5 + 10;
const int P = 998244353;
int n , m;
int v[MAXN];

int Pow( int x , int a ) {
	int ret = 1;
	while( a ) {
		if( a & 1 ) ret = ret * 1ll * x % P;
		x = x * 1ll * x % P , a >>= 1;
	}
	return ret;
}

int Wn[2][MAXN];
void getwn( int len ) {
	for( int mid = 1 ; mid < len ; mid <<= 1 ) {
		int w0 = Pow( 3 , ( P - 1 ) / ( mid << 1 ) ) , w1 = Pow( 3 , P - 1 - ( P - 1 ) / ( mid << 1 ) );
		Wn[0][mid] = Wn[1][mid] = 1;
		for( int i = 1 ; i < mid ; ++ i )
			Wn[0][mid + i] = Wn[0][mid + i - 1] * 1ll * w0 % P,
			Wn[1][mid + i] = Wn[1][mid + i - 1] * 1ll * w1 % P;
	}
}
int rev[MAXN];
void getr( int len ) {
	int l = __builtin_ctz( len ) - 1;
	for( int i = 1 ; i < len ; ++ i ) rev[i] = ( rev[i >> 1] >> 1 ) | ( ( i & 1 ) << l );
}
void NTT( vi& A , int len , int typ ) {
	for( int i = 0 ; i < len ; ++ i ) if( i < rev[i] ) swap( A[i] , A[rev[i]] );
	for( int mid = 1 ; mid < len ; mid <<= 1 )
		for( int i = 0 ; i < len ; i += ( mid << 1 ) )
			for( int j = i ; j < i + mid ; ++ j ) {
				int t0 = A[j] , t1 = A[j + mid] * 1ll * Wn[typ][j - i + mid] % P;
				A[j] = ( t0 + t1 > P ? t0 + t1 - P : t0 + t1 ) , A[j + mid] = ( t0 < t1 ? t0 - t1 + P : t0 - t1 );
			}
	if( typ ) for( int i = 0 , iv = Pow( len , P - 2 ) ; i < len ; ++ i ) A[i] = A[i] * 1ll * iv % P;
}
void NTT( int A[] , int len , int typ ) {
	for( int i = 0 ; i < len ; ++ i ) if( i < rev[i] ) swap( A[i] , A[rev[i]] );
	for( int mid = 1 ; mid < len ; mid <<= 1 )
		for( int i = 0 ; i < len ; i += ( mid << 1 ) )
			for( int j = i ; j < i + mid ; ++ j ) {
				int t0 = A[j] , t1 = A[j + mid] * 1ll * Wn[typ][j - i + mid] % P;
				A[j] = ( t0 + t1 > P ? t0 + t1 - P : t0 + t1 ) , A[j + mid] = ( t0 < t1 ? t0 - t1 + P : t0 - t1 );
			}
	if( typ ) for( int i = 0 , iv = Pow( len , P - 2 ) ; i < len ; ++ i ) A[i] = A[i] * 1ll * iv % P;
}
vi mul( vi A , vi B , int flg = 0 ) {
	if( A.empty() || B.empty() ) return vector<int> ();
	int S = A.size() + B.size() , len = 1;
	while( len <= S ) len <<= 1;
	getr( len );
	A.resize( len ) , B.resize( len );
	NTT( A , len , 0 ) , NTT( B , len , 0 );
	rep( i , 0 , len - 1 ) A[i] = A[i] * 1ll * B[i] % P;
	NTT( A , len , 1 );
	while( A.size() && A.back() == 0 ) A.pop_back();
	return A;
}

//template<typename T>
//T&& add( T&& A , T&& B ) {
//	if( A.size() > B.size() ) {
//		rep( i , 0 , B.size() - 1 ) A[i] += B[i];
//		return forward<T>( A );
//	} else {
//		rep( i , 0 , A.size() - 1 ) B[i] += A[i];
//		return forward<T>( B ); 
//	}
//}

vi add( vi A , vi B ) {
	if( A.size() > B.size() ) {
		rep( i , 0 , B.size() - 1 ) A[i] += B[i];
		return A;
	} else {
		rep( i , 0 , A.size() - 1 ) B[i] += A[i];
		return B;
	}
}

const int N = 3;
struct mtrx {
	vi A[3][3];
	mtrx operator * ( mtrx B ) {
		mtrx res;
		rep( i , 0 , N - 1 ) rep( j , 0 , N - 1 ) rep( k , 0 , N - 1 ) 
			res.A[i][j] = add( move( res.A[i][j] ) , mul( A[i][k] , B.A[k][j] ) );
		return res;
	}
	void init( int i ) {
		if( i <= 16 ) {
			A[0][0] = { 1 , -v[i] };
			A[1][0] = { 1 };
			A[2][1] = { 1 };
		} else if( i <= 65537 ) {
			A[0][0] = { 1 } , A[0][1] = { 0 , -v[i] };
			A[1][0] = { 1 };
			A[2][1] = { 1 };
		} else {
			A[0][0] = { 1 } , A[0][2] = { 0 , -v[i] };
			A[1][0] = { 1 } , A[2][1] = { 1 };
		}
	}
} A[MAXN] ;

mtrx mul( int l , int r ) {
	if( l == r ) 
		return A[l];
	int m = ( l + r >> 1 );
	return mul( l , m ) * mul( m + 1 , r );
}

int tmpa[MAXN];
void Inv( vi A , int B[] , int n ) { // B = inv A
	if( n == 1 ) return void( B[0] = Pow( A[0] , P - 2 ) );
	Inv( A , B , n + 1 >> 1 );
	int len = 1;
	while( len <= n + n ) len <<= 1;
	getr( len );
	for( int i = 0 ; i < n ; ++ i ) tmpa[i] = A[i];
	for( int i = n ; i < len ; ++ i ) tmpa[i] = 0;
	NTT( tmpa , len , 0 ) , NTT( B , len , 0 );
	rep( i , 0 , len - 1 ) B[i] = B[i] * ( 2 - tmpa[i] * 1ll * B[i] % P + P ) % P;
	NTT( B , len , 1 );
	rep( i , n , len - 1 ) B[i] = 0;
}

int as[MAXN];

void solve() {
	cin >> n >> m;
	rep( i , 1 , m ) scanf("%d",v + i) , A[i].init( i );
	mtrx pr;
	pr.A[0][0] = { 1 };
	mtrx res = mul( 1 , m ) * pr;
	vi re = res.A[0][0];
//	for( int x : re ) cout << x << endl;
	Inv( re , as , n + 1 );
	cout << as[n] << endl;
}

signed main() {
	getwn( 1 << 18 );
//	freopen("in","r",stdin);
//	freopen("out","w",stdout);
//	int T;cin >> T;while( T-- ) solve();
	solve();
}

詳細信息

Test #1:

score: 0
Time Limit Exceeded

input:

99990 99987
757148 167851001 301413357 336971125 659598369 160567226 391749388 4890852 35766291 26239573 473038165 597007 3615545 326051437 392289611 118341523 170427799 37215529 675016434 168544291 683447134 950090227 82426873 116752252 194041605 706221269 71664782 257655784 84970744 21417563 37379...

output:


result: