欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)

发布时间:2024/4/11 编程问答 55 豆豆
生活随笔 收集整理的这篇文章主要介绍了 上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

题目链接:点击查看

题目大意:给出两种型号的瓷砖,尺寸分别是 a∗1a*1a1b∗1b*1b1,现在需要填满 w∗hw*hwh 的矩阵,需要满足以下两个情况:

  • 瓷砖不能旋转
  • 相邻的两行中,前缀和不能有交集
  • 问方案数

    题目分析:因为 a,b,wa,b,wa,b,w 都特别小,按照题目要求爆搜以下不难看出,每一行最多有 114114114 种方案

    对于相邻的两行是否可以放置,我们可以维护一个可行矩阵 mazei,jmaze_{i,j}mazei,jmazei,j=1maze_{i,j}=1mazei,j=1 代表第 iii 种方案可以和第 jjj 种方案相邻,这个可以在时间复杂度 O(n2∗w)O(n^2*w)O(n2w) 的复杂度下预处理出来,因为时间复杂度还有冗余,所以我还加了个 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(矩阵快速幂)的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。