题目

image-1671457841897

题解

  • f[i][j]表示前i个骰子中,朝上的骰子数为j的个数
  • 由于重叠的骰子上下两个面互斥,需要将这两个面的数量除去。
  • 除此之外,每种情况都有四种不同的排列方法
#include<iostream>
#include<cstring>
using namespace std;
const int N=6,mod=1e9+7;
int n,m;
int get_op(int x){
    if(x>=3)return x-3;
    else return x+3;
}
void mul(int c[][N],int a[][N],int b[][N]){
    int t[N][N];
    memset(t,0,sizeof t);
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            for(int k=0;k<N;k++){
                t[i][j]=(t[i][j]+(long long)a[i][k]*b[k][j])%mod;
            }
        }
    }
    memcpy(c,t,sizeof t);
}
int main(){
    cin>>n>>m;
    int a[N][N];
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            a[i][j]=4;
    while(m--){
        int x,y;
        cin>>x>>y;
        x--,y--;
        a[x][get_op(y)]=0;//x和y的对面互斥
        a[y][get_op(x)]=0;//y和x的对面互斥
    }
    int f[N][N]={4,4,4,4,4,4};
    for(int k=n-1;k;k>>=1){
        if(k&1)mul(f,f,a);
        mul(a,a,a);
    }
    int res=0;
    for(int i=0;i<N;i++)res=(res+f[0][i])%mod;
    cout<<res<<endl;
    
    
    return 0;
}