上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出两种型号的瓷砖,尺寸分别是 a ∗ 1 a*1 a∗1 和 b ∗ 1 b*1 b∗1,现在需要填满 w ∗ h w*h w∗h 的矩阵,需要满足以下两个情况:
- 瓷砖不能旋转
- 相邻的两行中,前缀和不能有交集
问方案数
题目分析:因为 a , b , w a,b,w a,b,w 都特别小,按照题目要求爆搜以下不难看出,每一行最多有 114 114 114 种方案
对于相邻的两行是否可以放置,我们可以维护一个可行矩阵 m a z e i , j maze_{i,j} mazei,j, m a z e i , j = 1 maze_{i,j}=1 mazei,j=1 代表第 i i i 种方案可以和第 j j j 种方案相邻,这个可以在时间复杂度 O ( n 2 ∗ w ) O(n^2*w) O(n2∗w) 的复杂度下预处理出来,因为时间复杂度还有冗余,所以我还加了个 s e t set set 降低了代码复杂度
那么现在问题转换为:选择任意起点,走 h h h 步后,不同的方案数有多少
矩阵快速幂的模板题,套上模板就好了
代码:
// 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(矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章
上海理工大学第二届“联想杯”全国程序设计邀请赛 - Experiment Class(几何+三分套三分)
上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)
2021 ICPC全国邀请赛(西安)太原理工大学收获3枚奖牌