题意:给定2*2*n的立方体
我们认为1*1*1 的小格子是一个顶点
有公共面的顶点认为有一条无向边
给定n
问有多少条哈密顿回路
结论:a[n] = 4*a[n-1] - a[n-2]; (n>=3)
别问我怎么知道的,我也不知道。。。TAT
然后有注意一点,这里面涉及到了减法,矩阵快速幂后要注意ans可能<0 ,加个mod即可。
#include"cstdio" #include"iostream" #include"queue" #include"algorithm" #include"set" #include"queue" #include"cmath" #include"string.h" #include"vector" using namespace std; #define ll long long const ll mod = 1000000007; ll n; #define Matr 4 //矩阵大小,注意能小就小 struct mat//矩阵结构体,a表示内容,size大小 矩阵从1开始 { ll a[Matr][Matr],size; mat() { size=0; memset(a,0,sizeof(a)); } }; mat multi(mat m1,mat m2,ll mod)//两个相等矩阵的乘法,对于稀疏矩阵,有0处不用运算的优化 { mat ans=mat(); ans.size=m1.size; for(ll i = 1; i <= ans.size; i++) for(ll j = 1; j <= ans.size; j++) for(ll k = 1; k <= ans.size; k++) ans.a[i][j] = (ans.a[i][j]+m1.a[i][k]*m2.a[k][j])%mod; return ans; } mat quickmulti(mat m,ll n,ll mod)//二分快速幂 { mat ans=mat(); for(ll i=1;i<=m.size;i++)ans.a[i][i]=1; ans.size=m.size; while(n) { if(n&1)ans=multi(m,ans,mod); m=multi(m,m,mod); n>>=1; } return ans; } /* ans^=n -> mat ans=mat(); ans.size=Size; 初始化ans矩阵 ans=quickmulti(ans,n,mod); */ int main(){ ll T, Cas = 1;scanf("%lld",&T); while(T--){ scanf("%lld",&n); printf("Case %lld: ",Cas++); if(n==1)puts("1"); else if(n==2)puts("6"); else if(n==3)puts("22"); if(n<=3)continue; mat tmp=mat(); tmp.size = 2; tmp.a[1][1] = 4; tmp.a[1][2] = -1; tmp.a[2][1] = 1; tmp.a[2][2] = 0; tmp = quickmulti(tmp, n-3, mod); ll ans = tmp.a[1][1]*22+tmp.a[1][2]*6; ans %= mod; while(ans<0)ans+=mod; printf("%lld\n",ans); } return 0; }
PJOI 1024 Hamilton Circles 矩阵快速幂
时间: 2024-10-13 03:14:07