首页 > 代码库 > ACdream1093
ACdream1093
给你三种正多面体,正四面体,正六面体,正八面体。求从某一种正多面体中的某一点走到另一个点,且步数不超过k(1018)的方案数。
首先说明一下我交题的时候遇到的问题,起点和终点为同一点的时候,算不算走了零步到达了?题目没有算,如果考虑了交上去会wa。
题目解法是矩阵。
一开始通过观察这三种多面体,得出初始矩阵。 这里要细心。
显然我们可以通过矩阵乘法迅速地知道从一点到另一点走k步的方案数。假设矩阵是a[][],那么x->y的方案就是a[x][y]。
要求不超过k步的方案,就相当于前k个矩阵求和了(前k次方和)。因为矩阵有很多性质跟数是一样的,我们可以用类似的方法求解。
我也不知道自己用的是什么方法,反正这样写可以过。不过好像时间上不是最优的。
召唤代码君:
/** this code is made by 092000* Problem: 1093* Verdict: Accepted* Submission Date: 2014-07-20 10:06:15* Time: 592MS* Memory: 1676KB*/#include <iostream>#include <cstdio>#include <cstring>typedef long long ll;using namespace std; const int mod=1000000007;ll k;int n,I,J,T; int a4[4][4]={ {0,1,1,1}, {1,0,1,1}, {1,1,0,1}, {1,1,1,0}, }; int a6[6][6]={ {0,1,1,1,1,0}, {1,0,1,0,1,1}, {1,1,0,1,0,1}, {1,0,1,0,1,1}, {1,1,0,1,0,1}, {0,1,1,1,1,0},}; int a8[8][8]={ {0,1,0,1,1,0,0,0}, {1,0,1,0,0,1,0,0}, {0,1,0,1,0,0,1,0}, {1,0,1,0,0,0,0,1}, {1,0,0,0,0,1,0,1}, {0,1,0,0,1,0,1,0}, {0,0,1,0,0,1,0,1}, {0,0,0,1,1,0,1,0},}; struct mat{ ll a[8][8]; void init0() { memset(a,0,sizeof a); } void init1() { init0(); for (int i=0; i<n; i++) a[i][i]=1; } void init(int x) { init0(); if (x==4) { for (int i=0; i<4; i++) for (int j=0; j<4; j++) a[i][j]=a4[i][j]; } else if (x==6) { for (int i=0; i<6; i++) for (int j=0; j<6; j++) a[i][j]=a6[i][j]; } else { for (int i=0; i<8; i++) for (int j=0; j<8; j++) a[i][j]=a8[i][j]; } }}; mat add(mat e1,mat e2){ mat e0; for (int i=0; i<n; i++) for (int j=0; j<n; j++) e0.a[i][j]=(e1.a[i][j]+e2.a[i][j])%mod; return e0;} mat mul(mat e1,mat e2){ mat e0; e0.init0(); for (int i=0; i<n; i++) for (int j=0; j<n; j++) for (int k=0; k<n; k++) e0.a[i][j]=(e0.a[i][j]+e1.a[i][k]*e2.a[k][j])%mod; return e0;} mat power(mat e,ll y){ mat e0; e0.init1(); while (y) { if (y&1) e0=mul(e0,e); e=mul(e,e),y>>=1; } return e0;} int main(){ mat ans,tmp,squ,E; ll answer; scanf("%d",&T); while (T--) { scanf("%d",&n); scanf("%lld",&k); scanf("%d",&I); scanf("%d",&J); //scanf("%d%lld%d%d",&n,&k,&I,&J); if (n==8) n=6; else if (n==6) n=8; ans.init0(); tmp.init1(); squ.init1(); E.init(n); while (k) { if (k&1) ans=add(ans,mul(tmp,power(E,k))); k>>=1; tmp=mul(tmp,add(power(E,k),squ)); } answer=ans.a[I-1][J-1]; //if (I==J) answer++; answer%=mod; printf("%d\n",(int)answer); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。