f[i][j] 表示有i个筛子,第i个筛子朝上的点数为j的方案数
对于第i个筛子,只需要考虑第i-1个筛子中与其不矛盾的方案数之和
首先第一个筛子每个面朝上都有四种方案,不需要考虑矛盾
第i个筛子,枚举其朝上的点数j,其朝下点数为op[j],枚举第i-1个筛子朝上的点数k,判断k与op[j]是否有矛盾,若无矛盾则在第i个筛子朝上点数为j的方案上,累加第i-1个筛子朝上点数为k的方案数*4
注意若枚举第i个筛子,最终方案数为0时说明无法再继续进行,方案无解
由于筛子数量过大,表示筛子编号的第一维通过&1压缩到01即可
#include <iostream>
#include <cstring>
#include <algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
ll n,m;
const ll N=1e9+5,mod=1e9+7;
int st[7][7];
int op[]={0,4,5,6,1,2,3};
ll f[2][7];
ll dp()
{
//第一个筛子每个面朝上都有四种方案
for(int i=1;i<=6;i++)
f[1][i]=4;
//第2~n个筛子
for(int i=2;i<=n;i++)
{
ll t=0;
//第i个筛子上面的点数j,其下面的点数为op[j]
for(int j=1;j<=6;j++)
{ //第i-1个筛子上面的点数k
ll res=0;
for(int k=1;k<=6;k++)
{
if(st[k][op[j]]) continue;//存在矛盾
res+=(4*f[!(i&1)][k])%mod;
res%=mod;
}
t+=res;
f[i&1][j]=res;
}
if(!t) return 0;
}
ll res=0;
for(int i=1;i<=6;i++)
res=(res+f[n&1][i])%mod;
return res;
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b;cin>>a>>b;
st[a][b]=st[b][a]=true;
}
ll sum=dp();
if(!sum)
{
cout<<0<<endl;
return 0;
}
cout<<sum<<endl;
}