BZOJ5298: [Cqoi2018]交錯序列
阿新 • • 發佈:2018-11-06
題意
稱一個僅由 構成的序列為 “交錯序列”,當且僅當序列中沒有相鄰的 可以有相鄰的 ;定義一個交錯序列的特徵值為 ,其中 為系列中 的個數, 為序列中 的個數, 為給定的常數;求本質不同的長度 的交錯序列的特徵值的和;
題解
考慮將特徵值的式子用二項式定理展開:
現在我們的問題就變成了求每個 ;
因為特徵值的計算只跟 的個數有關,所以我們只關心 的個數,不關心那個序列到底長啥樣,但是 有 ,如果要算出每種序列的個數再去繼續處理的話其實並不好算,考慮直接定義一個狀態 表示用 和 去填滿這個序列,填到第 位時以 結尾的所有的 的和,也就是 , 是上面展開的式子中的 ,也就是 的個數;那麼有:
的轉移同樣可以通過二項式定理展開得到;
這恰好是一個線性遞推,考慮用矩陣快速冪加速,最後帶入展開的特徵值式子計算即可;
#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