你有\(s_1\)種\(1\times 2\)的地磚,\(s_2\)種\(2\times 1\)的地磚。
記鋪滿\(m\times n\)的地板的方案數為\(f(m,n)\)。
給你\(m,l,r,s_1,s_2\),求\(\sum_^rf(m,i)\)
\(m\leq 6,1\leq l\leq r\leq ^\)
顯然是狀壓dp。
顯然可以矩陣快速冪。
怎麼矩陣快速冪?
假設矩陣是\(2^m\times 2^m\)的,我們把矩陣擴大一行一列,記錄前面算出的鋪滿\(m\)行\(i\)列的方案數。
轉移在原來轉移的基礎上增加\(f_\longrightarrow f_\)和\(f_\longrightarrow f_\)
這樣\(f_\)就是\(\sum_^f_\)。
然後就可以矩陣快速冪了。
顯然這個矩陣快速冪是可以用特徵多項式+倍增取模優化的。
求特徵多項式可以用\(o(n^3)\)的方法,也可以用\(o(n^4)\)的方法。
然後就沒了。
時間複雜度:\(o(8^m+4^m\log r)\)
求矩陣的特徵多項式
cayley-hamilton定理&倍增取模
#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
typedef pairpii;
void open(const char *s)
typedef vectorpoly;
const ll p=998244353;
ll fp(ll a,ll b)
struct matrix
ll *operator (int x) };
matrix operator *(matrix a,matrix b)
for(int j=i+2;j<=n;j++)
if(a[j][i])
} f[n+1].push_back(1);
for(int i=n;i>=0;i--)
}return f[0]; }}
matrix a;
int m,s1,s2,all;
void dfs(int x,int a1,int a2,ll s)
dfs(x+1,a1,a2,s);
dfs(x+1,a1|(1<<(x-1)),a2|(1<<(x-1)),s*s1%p);
dfs(x+2,a1,a2|(3<<(x-1)),s*s2%p);
}poly aa;
int len;
//poly f[20];
matrix g[200];
poly operator *(poly a,poly b)
poly operator %(poly a,poly b)
while(!a.back())
a.pop_back();
return a;
}poly a1;
void init()
n=max(n,i);
memset(bit,0,sizeof bit);
int k=1;
for(int i=n;i>=1;i--)
k=max(k,j);
bit[1]+=e[i];
for(j=1;bit[j]>=2;j++)
k=max(k,j);
} f.clear();
f.push_back(1);
reverse(bit+1,bit+k+1);
calc(k);
ll ans=0;
for(int i=0;ireturn ans;
}int main()
XSY 3327 思維 跑步
題意 給你乙個nn的網格。初始時,每個網格有乙個非負權值。有n次操作。每次操作會將乙個網格的權值加1或減1。權值操作後仍非負 輸出當前每個網格到11的最長路 每步向上或向左 的總和。n 2000 n leqslant 2000 n 2000 解法 這是一道好題!我太菜了,做不出。我們考慮維護dp值。...
XSY3904 直線(分塊)
直線 注意到題目沒有給什麼特殊的性質,除了直線隨機生成。所以考慮隨機化演算法或均攤演算法。有一種很神奇的分塊做法 考慮將整個平面分成 b b b times b b b 塊,每塊大小 109 b 10 9b dfrac times dfrac b109 b109 而且每乙個塊記錄一下有哪些直線經過它...
xsy 相似字串
輸入第1行,包含3個整數n,q。q代表詢問組數。第2行是字串s。接下來q行,每行兩個整數i和j。1 i j 輸出共q行,每行乙個數表示每組詢問的答案。如果不存在第i個子串或第j個子串,則輸出 1。關於這道題的每個詢問首先要求出第i小和第j小的子串在原串的位置,然後快速地求出這兩個子串的最長公共字首和...