上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)
生活随笔
收集整理的這篇文章主要介紹了
上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出兩種型號的瓷磚,尺寸分別是 a?1a*1a?1 和 b?1b*1b?1,現在需要填滿 w?hw*hw?h 的矩陣,需要滿足以下兩個情況:
問方案數
題目分析:因為 a,b,wa,b,wa,b,w 都特別小,按照題目要求爆搜以下不難看出,每一行最多有 114114114 種方案
對于相鄰的兩行是否可以放置,我們可以維護一個可行矩陣 mazei,jmaze_{i,j}mazei,j?,mazei,j=1maze_{i,j}=1mazei,j?=1 代表第 iii 種方案可以和第 jjj 種方案相鄰,這個可以在時間復雜度 O(n2?w)O(n^2*w)O(n2?w) 的復雜度下預處理出來,因為時間復雜度還有冗余,所以我還加了個 setsetset 降低了代碼復雜度
那么現在問題轉換為:選擇任意起點,走 hhh 步后,不同的方案數有多少
矩陣快速冪的模板題,套上模板就好了
代碼:
// Problem: Little Witch Academia // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/17574/L // Memory Limit: 524288 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; const int mat_size = 150;//矩陣大小,需要乘以2,為了&運算的時候需要二倍的矩陣大小 const int mod=1e9+7; struct Matrix {long long a[mat_size][mat_size];int x, y;//長寬Matrix() //返回0矩陣{memset(a,0,sizeof(a));}Matrix(int x,int y)//返回0矩陣,并且x,y賦值{this->x = x;this->y = y;memset(a, 0,sizeof(a));}Matrix(int n) //返回n*n的【單位矩陣】{this->x=n;this->y=n;memset(a,0,sizeof(a));for (int i = 0; i <n;++i) a[i][i]=1;}Matrix operator * (const Matrix &B)//矩陣乘法{Matrix tmp;for (int i = 0; i < x; ++ i)for (int j = 0; j < B.y; ++ j){tmp.a[i][j] = 0;for (int k = 0; k < y; ++ k){tmp.a[i][j] = (tmp.a[i][j] + a[i][k] * B.a[k][j] % mod) % mod;}}tmp.x = x;tmp.y=B.y;return tmp;}Matrix operator ^ (long long b)//矩陣A的b次方{Matrix ret = Matrix(x); Matrix A = *this;while( b ) { if( b & 1 ) ret = ret * A ; b >>= 1 ; A = A * A ; } return ret ; }Matrix operator & (int b)//A^0 + A^1+A^2+A^3+++A^n,其中A是矩陣。最后返回的就是一個矩陣{Matrix ret = *this;for (int i = ret.x; i < ret.x * 2; ++ i) {ret.a[i-ret.x][i]= 1;ret.a[i][i] = 1;}ret.x <<= 1;ret.y <<= 1;//pg(ret);ret = ret^b;ret.x >>= 1;ret.y >>= 1;for (int i = 0; i < ret.x; ++ i) for (int j = 0; j < ret.y; ++ j)(ret.a[i][j] += ret.a[i][j + ret.x])%=mod;return ret;}void pg(Matrix A){for (int i = 0; i <A.x; ++i){for (int j = 0; j < A.y;++j) cout<<A.a[i][j]<<" ";cout<<endl;}cout<<endl;} }maze; int a,b,w,h; vector<int>tmp; vector<vector<int>>node; void dfs(int cur) {if(cur>w) {return;}if(cur==w) {node.push_back(tmp);return;}tmp.push_back(a);dfs(cur+a);tmp.pop_back();tmp.push_back(b);dfs(cur+b);tmp.pop_back(); } bool check(vector<int>a,vector<int>b) {set<int>st;int sum=0;for(auto it:a) {sum+=it;st.insert(sum);}sum=0;for(auto it:b) {sum+=it;if(sum!=w&&st.count(sum)) {return false;}}return true; } void build() {maze=Matrix(node.size(),node.size());for(int i=0;i<(int)node.size();i++) {for(int j=0;j<(int)node.size();j++) {maze.a[i][j]=check(node[i],node[j]);}} } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int t;cin>>t;while(t--) {node.clear();tmp.clear();read(a),read(b),read(w),read(h);dfs(0);build();maze=maze^(h-1);LL ans=0;for(int i=0;i<maze.x;i++) {for(int j=0;j<maze.y;j++) {ans=(ans+maze.a[i][j])%mod;}}cout<<ans<<endl;}return 0; }總結
以上是生活随笔為你收集整理的上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上海理工大学第二届“联想杯”全国程序设计
- 下一篇: CodeForces - 1534E L