[caioj 1487及vijos 1194,利用矩阵乘法解决的经典题目九]有趣的domino
2017-08-26 16:55
429 查看
问用1*2的多米诺骨牌填满m*n的矩阵有多少种方案,结果需要mod p。
这道题看上去跟矩阵乘法八竿子都打不着边,但是我们可以转换模型。其实我们可以将这个m*n矩阵的状态通过位运算转换成二进制状态,具体就是先假设i是前一个状态,而j是这一个状态,那么i状态到j状态的条件就是i or j=k 且 i and j=s[x] (0<=x<8),s[]={0,3,6,12,15,24,27,30};为什么这样做,因为当i状态和j状态在某个位置必须至少有一个是1,如果i是1,j是0,那么就说明这个地方不用放骨牌,如果i是0,j是1那么就是放骨牌。如果i和j都是1,那么说明原来这个地方有骨牌了,现在还有,那么一定是横着放的骨牌,而s数据的作用就是判断i与j是不是连续的1,转换成二进制就可以看出来了。最后只要条件符合,将这些二进制状态转换成一个矩阵,再平方n次,这题就解决了。(注意:vijos与caioj的n,m输入顺序是相反的)
这道题看上去跟矩阵乘法八竿子都打不着边,但是我们可以转换模型。其实我们可以将这个m*n矩阵的状态通过位运算转换成二进制状态,具体就是先假设i是前一个状态,而j是这一个状态,那么i状态到j状态的条件就是i or j=k 且 i and j=s[x] (0<=x<8),s[]={0,3,6,12,15,24,27,30};为什么这样做,因为当i状态和j状态在某个位置必须至少有一个是1,如果i是1,j是0,那么就说明这个地方不用放骨牌,如果i是0,j是1那么就是放骨牌。如果i和j都是1,那么说明原来这个地方有骨牌了,现在还有,那么一定是横着放的骨牌,而s数据的作用就是判断i与j是不是连续的1,转换成二进制就可以看出来了。最后只要条件符合,将这些二进制状态转换成一个矩阵,再平方n次,这题就解决了。(注意:vijos与caioj的n,m输入顺序是相反的)
#include<cstdio> #include<cmath> #include<algorithm> #include<cstdlib> #include<cstring> using namespace std; struct node { long long a[35][35]; node() { memset(a,0,sizeof(a)); } }; int he; long long p; int s[8]={0,3,6,12,15,24,27,30}; node chengfa(node a,node b) { node c; for(int i=0;i<he;i++) { for(int j=0;j<he;j++) { for(int k=0;k<he;k++) { c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%p; } } } return c; } int main() { int m;long long n; node pre,ans; he=1; scanf("%lld%d%lld",&n,&m,&p); for(int i=1;i<=m;i++)he*=2; for(int i=0;i<he;i++)ans.a[i][i]=1; for(int i=0;i<he;i++) { for(int j=0;j<he;j++) { if(((~i)&j)==((~i)&(he-1))) { int bk=0; for(int k=0;k<8;k++) { if((i&j)==s[k])bk=bk||(i&j)==s[k]; } pre.a[i][j]=bk; } } } long long x=n; while(x>0) { if(x%2==1)ans=chengfa(pre,ans); pre=chengfa(pre,pre); x/=2; } printf("%lld\n",ans.a[he-1][he-1]); return 0; }
相关文章推荐
- [caioj 1485及vijos 1067,利用矩阵乘法解决的经典题目七]童年的走格子
- [caioj 1482及vijos 1049,利用矩阵乘法解决的经典题目四]序列无限变
- [caioj 1483,利用矩阵乘法解决的经典题目五]成群的细菌
- [caioj 1484及Luogu P1962,利用矩阵乘法解决的经典题目六]Fibonacci数列
- [caioj 1480,利用矩阵乘法解决的经典题目二]矩阵无限方
- [caioj 1479,利用矩阵乘法解决的经典题目一]点的变换
- 【转】Matrix67:十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目(转Matrix67)
- 十个利用矩阵乘法解决的经典题目-Matrix67
- 学习心得:《十个利用矩阵乘法解决的经典题目》from Matrix67
- 十个利用矩阵乘法解决的经典题目(From Matrix67)
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目(Maxtrix67)(转)
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目
- 十个利用矩阵乘法解决的经典题目