矩阵快速幂+波利亚定理
波利亚可以解决同构问题
前三条列出递推矩阵
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=10;
const int mod=1e9+7;
typedef __int64 LL;
void cp(LL A[N][N],LL B[N][N],int n){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
A[i][j]=B[i][j];
}
}
}
LL D[N][N];
void _mul(LL A[N][N],LL B[N][N],int n){
memset(D,0,sizeof(D));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
D[i][j]+=A[i][k]*B[k][j]%mod;
D[i][j]%=mod;
}
}
}
cp(A,D,n);
}
LL C[N][N];
void _pow(LL A[N][N],int b,int n){
memset(C,0,sizeof(C));
for(int i=0;i<n;i++){
C[i][i]=1;
}
while(b){
if(b&1){
_mul(C,A,n);
}
_mul(A,A,n);
b/=2;
}
cp(A,C,n);
}
LL A[N][N];
void gun(int a,int b){
A[b][a]=1;
}
int mp[N][N];
void getA(){
int cnt=1;
for(int i=0;i<2;i++){
for(int j=2;j<4;j++){
mp[i][j]=cnt++;
}
}
for(int i=2;i<4;i++){
for(int j=0;j<2;j++){
mp[i][j]=cnt++;
}
}
memset(A,0,sizeof(A));
for(int i=0;i<2;i++){
for(int j=2;j<4;j++){
for(int k=0;k<2;k++){
gun(mp[i][j],mp[j][k]);
}
}
}
for(int i=2;i<4;i++){
for(int j=0;j<2;j++){
for(int k=2;k<4;k++){
if(j!=0)gun(mp[i][j],mp[j][k]);
if(j==0&&i==k)gun(mp[i][j],mp[j][k]);
}
}
}
A[0][0]=1;
for(int i=1;i<cnt;i++){
for(int j=1;j<cnt;j++){
A[0][i]+=A[j][i];
}
}
}
LL fun1(int n){
if(n==0)return 0;
if(n==1)return 4;
n-=2;
getA();
int cnt=9;
_pow(A,n,cnt);
LL ans=A[0][0]*12;
for(int i=1;i<cnt;i++){
ans+=A[0][i];
ans%=mod;
}
return ans;
}
LL _pow2(LL a,int b){
LL c=1;
while(b){
if(b&1){
c*=a;c%=mod;
}
a*=a;a%=mod;b/=2;
}
return c;
}
LL fun(int n){
LL a,b;
a=fun1(n),b=fun1((n+1)/2);
//printf("%I64d:%d %I64d:%d\n",a,n,b,n/2);
return (a+b)*_pow2(2,mod-2)%mod;
}
LL dp[100][10];
LL getdp(int n){
if(n==1)return 4;
getA();
for(int i=1;i<=8;i++){
dp[2][i]=1;
}
// for(int i=1;i<=8;i++){
// for(int j=1;j<=8;j++){
// printf("%I64d ",A[i][j]);
// }printf("\n");
// }
for(int i=3;i<=n;i++){
for(int j=1;j<=8;j++){
dp[i][j]=0;
for(int k=1;k<=8;k++)if(A[j][k]){
dp[i][j]+=dp[i-1][k];
}
}
}
LL ans=0;
for(int i=1;i<=8;i++){
ans+=dp[n][i];
}
return ans;
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
int L,R;
// for(int i=0;i<=10;i++){
// printf("%I64d %I64d %d\n",fun1(i),getdp(i),i);
// }
while(scanf("%d%d",&L,&R)!=EOF){
printf("%I64d\n",(fun(R)-fun(L-1)+mod)%mod);
//printf("%I64ddp\n",getdp(R));
}
return 0;
}
本文介绍了一种结合矩阵快速幂和波利亚定理解决同构问题的方法。通过构造特定递推矩阵并利用矩阵快速幂进行高效计算,解决了计数问题。代码实现了核心算法,并提供了计算实例。
476

被折叠的 条评论
为什么被折叠?



