题意:给定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;
}