原题链接

考察:线性dp+矩阵快速幂

思路:
        将限制条件作为动态规划的维度,某两个数字不能紧连,这只与骰子的上面或下面有关,可以用f[i][j] 表示第i个骰子,其最上面是j.f[i][j] = f[i-1][k]*4,j的对面与k不互斥,骰子可以绕中心旋转.如果互斥常数就是0.时间复杂度n*6*6

        因为n过大,所以需要优化算法.这里涉及到矩阵快速幂.因为f[i][j] += f[i-1][k]*4,(1<=j<=6&&1<=k<=6)是相乘累加,可以考虑设置6维向量.f[i][j] 表示 {f[i][1],f[i][2]..f[i][6]}.a数组则是系数数组,不是0就是4.

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N = 7,Mod = 1e9+7;
 7 int re[N],mp[N][N],ans;
 8 void mul(int f[],int a[][N])
 9 {
10     int res[N];
11     memset(res,0,sizeof res);
12     for(int i=1;i<=6;i++)
13       for(int j=1;j<=6;j++)
14         res[i] = (res[i]+(LL)f[j]*a[j][i])%Mod;
15     memcpy(f,res,sizeof res);
16 }
17 void mulself(int a[][N])
18 {
19     int res[N][N];
20     memset(res,0,sizeof res);
21     for(int i=1;i<=6;i++)
22       for(int j=1;j<=6;j++)
23         for(int k=1;k<=6;k++)
24           res[i][j] = (res[i][j]+(LL)a[i][k]*a[k][j])%Mod;
25     memcpy(a,res,sizeof res);
26 }
27 int main()
28 {
29     for(int i=1;i<=3;i++) re[i] = i+3,re[i+3] = i;
30     for(int i=1;i<=6;i++)
31       for(int j=1;j<=6;j++) mp[i][j] = 4;
32     int n,m;
33     scanf("%d%d",&n,&m) ;
34     while(m--)
35     {
36         int x,y; scanf("%d%d",&x,&y);
37         mp[x][re[y]] = 0,mp[y][re[x]] = 0;
38     }
39     int f[N] = {0,4,4,4,4,4,4};
40     n--;
41     while(n)
42     {
43         if(n&1) mul(f,mp);
44         mulself(mp);
45         n>>=1;
46     }
47     for(int i=1;i<=6;i++) ans = (ans+f[i])%Mod;
48     printf("%d\n",ans);
49     return 0;
50 }