Luogu3977 [TJOI2015]棋盤
阿新 • • 發佈:2020-07-30
Description
給定一個大小為 \(n \times m\) 的棋盤,同時給定一個棋子的攻擊範圍的情況,是一個 \(3 \times p\) 的矩陣
要求放置棋子的方案數
\(p \le m ,n\le 10^6,m\le 6\)
Solution
這真的是閱讀理解題,請仔細分析 \(0/1\) 後判斷每個棋子的攻擊範圍
然後狀壓這部分就是一個考驗程式碼能力的部分……(比如我寫了倆小時,旁邊的 \(@happyguy\) 就寫了半小時……)
然後這樣並不能通過本題,畢竟複雜度在那裡……
然後我們發現這個轉移是有向的……(這部分抄了題解……畢竟不會矩陣加速)
兩個狀態之間就是兩個狀態之間的指向性轉移
然後建立初始矩陣,快速冪
Code
#include<bits/stdc++.h> using namespace std; namespace yspm{ inline int read() { int res=0,f=1; char k; while(!isdigit(k=getchar())) if(k=='-') f=-1; while(isdigit(k)) res=res*10+k-'0',k=getchar(); return res*f; } const int N=1e6+10; bool vis[4][10],abl[100],t1[100][100],t2[100][100]; int n,m,k,p,s; #define ui unsigned int struct node{ ui a[100][100]; ui* operator[](int x){return a[x];} inline void init(){memset(a,0,sizeof(a)); return ;} inline void work(){for(int i=0;i<=s;++i) a[i][i]=1; return ;} }b,a; inline node mul(node a,node b) { node res; res.init(); for(int i=0;i<=s;++i) { for(int j=0;j<=s;++j) { for(int k=0;k<=s;++k) res[i][j]+=a[i][k]*b[k][j]; } } return res; } inline bool judge1(int x,int y) { if(!abl[x]||!abl[y]) return 0; for(int i=1;i<=m;++i) { if(!(x&(1<<(i-1)))) continue; int t=i-k; for(int j=1;j<=m;++j) { if(j+t<1) continue; if(j+t>m) continue; if(!vis[3][j]) continue; if(y&(1<<(j+t-1))) return 0; } } return 1; } inline bool judge2(int x,int y) { if(!abl[x]||!abl[y]) return 0; for(int i=1;i<=m;++i) { if(!(x&(1<<(i-1)))) continue; int t=i-k; for(int j=1;j<=m;++j) { if(j+t<1) continue; if(j+t>m) continue; if(!vis[1][j]) continue; if(y&(1<<(j+t-1))) return 0; } } return 1; } inline bool c1(int x) { for(int i=1;i<=m;++i) { if(!(x&(1<<(i-1)))) continue; int t=i-k; for(int j=1;j<=p;++j) { if(!vis[2][j]) continue; if(j+t<1) continue; if(j+t>m) continue; if(x&(1<<(j+t-1))) return 0; } } return 1; } signed main() { n=read(); m=read(); p=read(); k=read()+1; for(int i=1;i<=3;++i) { for(int j=1;j<=p;++j) vis[i][j]=read(); } vis[2][k]=0; s=(1<<m)-1; for(int i=0;i<=s;++i) abl[i]=c1(i); for(int i=0;i<=s;++i) { for(int j=0;j<=s;++j) t1[i][j]=judge1(i,j); } for(int i=0;i<=s;++i) { for(int j=0;j<=s;++j) t2[i][j]=judge2(i,j); } for(int j=0;j<=s;++j) { for(int k=0;k<=s;++k) { if(t1[j][k]&&t2[k][j]) b[j][k]++; } } a=b; --n; for(;n;n>>=1,a=mul(a,a)) if(n&1) b=mul(b,a); ui ans=0; for(int i=0;i<=s;++i) ans+=b[n][i]; cout<<ans<<endl; return 0; } } signed main(){return yspm::main();}