hdu 5411 CRB and Puzzle 矩阵快速幂
|字数总计:1.9k|阅读时长:11分钟|阅读量:
题意:有n种数量无限的方块,每种方块后可以拼接另一个方块,但是只能拼接给定种类的方块,问最多拼接M次能拼接出多少种不同的样式。
这道题中n只有50,很容易想到矩阵快速幂,毕竟这种题已经烂大街了。然而比赛的时候我居然没有读到这道题!!!!!
重点在于构造转移矩阵,显然如果a后面可以拼接b,那么有tmp[a][b]=1;代表a->b有一种转移方式,构造完了之后,对这个矩阵自乘m次,那么矩阵的结果tmp′[a][b]代表的就是起点为a,终点为b,经过m次转移的方法数,但是我们要求0次转移 1次转移 2次转移 。。。M次转移的总和,所以把最后一列赋为1,就可以了。
第一次写的时候矩阵构造太挫T了,然后优化了一点勉强过了,
第二次和第三次都是优化过的。
优化过的矩阵构造。
代码1:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits>
using namespace std; typedef long long LL; const int INF = numeric_limits<int>::max(); const LL LL_INF= numeric_limits<LL>::max(); const int N = 53; const int mod=2015; int T,n,m,k,tn;
void matric_mul(int A[][N],int B[][N],int C[][N]){ int t[N][N]={0}; for(int k=0;k<tn;k++){ for(int i=0;i<tn;i++){ if(A[i][k]==0)continue; for(int j=0;j<tn;j++){ t[i][j]+=A[i][k]*B[k][j]; t[i][j]%=mod; } } } for(int i=0;i<tn;i++){ for(int j=0;j<tn;j++){ C[i][j]=t[i][j]; } } } int res[N][N],tmp[N][N]; void print(int A[][N]){ for(int i=0;i<tn;i++,puts("")) for(int j=0;j<tn;j++)printf("%d ",A[i][j]); puts(""); } int q_pow(int nn){ while(nn>0){ if(nn&1)matric_mul(res,tmp,res); nn>>=1; matric_mul(tmp,tmp,tmp); } int cnt=res[0][n]; return (cnt+1)%mod; } void Rd(int &x){ char ch; while((ch=getchar())&&!isdigit(ch)); x=0; do { x=(x<<3)+(x<<1)+(ch^48); }while((ch=getchar())&&isdigit(ch)); } int main() { int maxn=0,maxm=0; scanf("%d",&T); while(T--){ Rd(n),Rd(m); maxn=max(n,maxn),maxm=max(m,maxm); tn=n+1; memset(tmp,0,sizeof(tmp)); memset(res,0,sizeof(res)); for(int i=0,x;i<n;i++){ Rd(k); for(int j=0;j<k;j++){ Rd(x); --x; tmp[i][x]=1; } } for(int i=0;i<=n;i++)tmp[i][n]=1; for(int i=0;i<n;i++)res[0][i]=1; res[0][n]=0; printf("%d\n",q_pow(m)); } return 0; }
|
代码2:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits>
using namespace std; typedef long long LL; const int INF = numeric_limits<int>::max(); const LL LL_INF= numeric_limits<LL>::max(); const int N = 52; const int mod=2015; int T,n,m,k,tn;
void matric_mul(int A[][N],int B[][N],int C[][N]){ int t[N][N]={0}; for(int k=0;k<tn;k++){ for(int i=0;i<tn;i++){ if(A[i][k]==0)continue; for(int j=0;j<tn;j++){ t[i][j]+=A[i][k]*B[k][j]; t[i][j]%=mod; } } } for(int i=0;i<tn;i++){ for(int j=0;j<tn;j++){ C[i][j]=t[i][j]; } } } int res[N][N],tmp[N][N]; void print(int A[][N]){ for(int i=0;i<tn;i++,puts("")) for(int j=0;j<tn;j++)printf("%d ",A[i][j]); puts(""); } int q_pow(int nn){ while(nn>0){ if(nn&1)matric_mul(res,tmp,res); nn>>=1; matric_mul(tmp,tmp,tmp); } int cnt=0; for(int i=0;i<tn;i++) for(int j=0;j<tn;j++)cnt+=res[i][j]; return (cnt)%mod; } void Rd(int &x){ char ch; while((ch=getchar())&&!isdigit(ch)); x=0; do { x=(x<<3)+(x<<1)+(ch^48); }while((ch=getchar())&&isdigit(ch)); } int main() { scanf("%d",&T); while(T--){ Rd(n),Rd(m); tn=n+1; memset(tmp,0,sizeof(tmp)); memset(res,0,sizeof(res)); for(int i=0;i<=n;i++)res[i][i]=1; for(int i=0,x;i<n;i++){ Rd(k); for(int j=0;j<k;j++){ Rd(x); --x; tmp[i][x]=1; } } for(int i=0;i<=n;i++)tmp[i][n]=1; printf("%d\n",q_pow(m-1)); } return 0; }
|
代码3:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits>
using namespace std; typedef long long LL; const int INF = numeric_limits<int>::max(); const LL LL_INF= numeric_limits<LL>::max(); const int N = 100; const int mod=2015; int T,n,m,k,tn;
void matric_mul(int A[][N],int B[][N],int C[][N]){ int t[N][N]={0}; for(int k=0;k<tn;k++){ for(int i=0;i<tn;i++){ if(A[i][k]==0)continue; for(int j=0;j<tn;j++){ t[i][j]+=A[i][k]*B[k][j]; t[i][j]%=mod; } } } for(int i=0;i<tn;i++){ for(int j=0;j<tn;j++){ C[i][j]=t[i][j]; } } } int res[N][N],tmp[N][N]; void print(int A[][N]){ for(int i=0;i<tn;i++,puts("")) for(int j=0;j<tn;j++)printf("%d ",A[i][j]); puts(""); } int q_pow(int nn){ while(nn>0){ if(nn&1)matric_mul(res,tmp,res); nn>>=1; matric_mul(tmp,tmp,tmp); } int cnt=0; for(int i=n;i<tn;i++)cnt+=res[0][i]; return (cnt+1)%mod; } void Rd(int &x){ char ch; while((ch=getchar())&&!isdigit(ch)); x=0; do { x=(x<<3)+(x<<1)+(ch^48); }while((ch=getchar())&&isdigit(ch)); } int main() { int maxn=0,maxm=0; scanf("%d",&T); while(T--){ Rd(n),Rd(m); maxn=max(n,maxn),maxm=max(m,maxm); tn=2*n; memset(tmp,0,sizeof(tmp)); memset(res,0,sizeof(res)); for(int i=0,x;i<n;i++){ Rd(k); for(int j=0;j<k;j++){ Rd(x); --x; tmp[i][x]=1; tmp[i][x+n]=1; } } for(int i=n;i<tn;i++)tmp[i][i]=1; for(int i=0;i<tn;i++)res[0][i]=1; printf("%d\n",q_pow(m-1)); } return 0; }
|