1. 程式人生 > >BZOJ5298: [Cqoi2018]交錯序列

BZOJ5298: [Cqoi2018]交錯序列

BZOJ

題意

稱一個僅由 0 , 1 0,1 構成的序列為 “交錯序列”,當且僅當序列中沒有相鄰的 1 (

1( 可以有相鄰的 0 ) 0) ;定義一個交錯序列的特徵值為 x a
y b x^a*y^b
,其中 x x
為系列中 0 0 的個數, y y 為序列中 1 1 的個數, a , b a,b 為給定的常數;求本質不同的長度 n n 的交錯序列的特徵值的和;

題解

考慮將特徵值的式子用二項式定理展開:
x a y b x^a*y^b ( n y ) a y b (n-y)^a*y^b ( i = 0 a C a i n a i ( y ) i ) y b (\sum_{i=0}^aC_a^i*n^{a-i}*(-y)^i)*y^b i = 0 a ( 1 ) i C a i n a i y b + i \sum_{i=0}^a(-1)^i*C_a^i*n^{a-i}*y^{b+i} 現在我們的問題就變成了求每個 y i ( 0 i a + b ) y^i(0\leq i\leq a+b) ;
因為特徵值的計算只跟 01 01 的個數有關,所以我們只關心 01 01 的個數,不關心那個序列到底長啥樣,但是 n n 1 0 8 10^8 ,如果要算出每種序列的個數再去繼續處理的話其實並不好算,考慮直接定義一個狀態 F [ i ] [ j ] [ 0 / 1 ] F[i][j][0/1] 表示用 0 0 1 1 去填滿這個序列,填到第 i i 位時以 1 / 0 1/0 結尾的所有的 y j y^j 的和,也就是 F [ i ] [ j ] [ 0 / 1 ] = y = 0 n y j F[i][j][0/1]=\sum_{y=0}^ny^j , y y 是上面展開的式子中的 y y ,也就是 1 1 的個數;那麼有:
F [ i ] [ j ] [ 0 ] = F [ i 1 ] [ j ] [ 0 ] + F [ i 1 ] [ j ] [ 1 ] F[i][j][0]=F[i-1][j][0]+F[i-1][j][1] F [ i ] [ j ] [ 1 ] = r = 0 j C j i F [ i 1 ] [ j ] [ 0 ] F[i][j][1]=\sum_{r=0}^jC_j^i*F[i-1][j][0] 1 1 的轉移同樣可以通過二項式定理展開得到;
這恰好是一個線性遞推,考慮用矩陣快速冪加速,最後帶入展開的特徵值式子計算即可;

#include<bits/stdc++.h>
#define Fst first
#define Snd second
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned int UI;
typedef unsigned long long ULL;
template<typename T> inline void read(T& x) {
	char c = getchar();
	bool f = false;
	for (x = 0; !isdigit(c); c = getchar()) {
		if (c == '-') {
			f = true;
		}
	}
	for (; isdigit(c); c = getchar()) {
		x = x * 10 + c - '0';
	}
	if (f) {
		x = -x;
	}
}
template<typename T, typename... U> inline void read(T& x, U& ... y) {
	read(x), read(y...);
}
int n,P,LIM;
int C[200][200],POW[100];
struct Matrix {
	int M[182][182];
}A,B;
typedef Matrix Mt;
void ADD(int &a,int b) {
	a+=b; if(a>=P) a-=P;
}
Mt operator *(Mt a,Mt b) {
	Mt c;
	for(int i=0;i<LIM;++i)
		for(int j=0;j<LIM;++j)
			c.M[i][j]=0;
	for(int i=0;i<LIM;++i) {
		for(int k=0;k<LIM;++k) if(a.M[i][k]) {
			for(int j=0;j<LIM;++j) if(b.M[k][j]) {
				ADD(c.M[i][j],1ll*a.M[i][k]*b.M[k][j]%P);
			}
		}
	}
	return c;
}
Mt Pow(Mt a,int k) {
	Mt res;
	for(int i=0;i<LIM;++i)
		for(int j=0;j<LIM;++j)
			res.M[i][j]=i==j;
	for(int i=k