题解:P8624 [蓝桥杯 2015 省 AB] 垒骰子

P8624 题解

题面

原题传送门

思路

首先看完题目很自然的想到可以设 \(dp_{i,j}\) 表示第 \(i\) 个骰子以 \(j\) 面朝上的方案数。

首先对立关系由于总共才 \(6\) 种情况,所以可以直接用一个二维数组 \(mp_{i,j}\) 来存,\(i,j\) 排斥为 \(0\),否则为 \(1\)

初始化就是 \(dp_1\) 的所有方案数为 \(1\)

考虑转移,\(\begin{aligned}dp_{i,j}=\sum_{k=1}^6 dp_{i-1,opp_k}\times mp_{j,opp_k}\end{aligned}\)

其中,\(opp_i\) 表示 \(i\) 的对面。

opp[10]={0,4,5,6,1,2,3}

但是 \(n\leq10^9\),这么做显然是不行的,考虑矩阵加速。

对于样例,我们有如下式子。

\(\begin{bmatrix}dp_{n,1}\\dp_{n,2}\\dp_{n,3}\\dp_{n,4}\\dp_{n,5}\\dp_{n,6}\end{bmatrix}=\begin{bmatrix}1&1&1&1&0&1\\1&1&1&0&1&1\\1&1&1&1&1&1\\1&1&1&1&1&1\\1&1&1&1&1&1\\1&1&1&1&1&1\end{bmatrix}^{n-1}\times\begin{bmatrix}dp_{n-1,1}\\dp_{n-1,2}\\dp_{n-1,3}\\dp_{n-1,4}\\dp_{n-1,5}\\dp_{n-1,6}\end{bmatrix}\)

统计答案 \(ans\) 非常简单,就直接将最终得到的矩阵的值全部加起来即可。

当然这样子是不行的,因为每一个筛子因为侧边是可以旋转的,都有 \(4\) 种摆法,所以最终得到的 \(ans\) 还得乘上 \(4^n\),快速幂解决即可(记得取模。。。)。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int MN=40;
const int mod=1e9+7;
ll n,m,u,v,mp[MN][MN],ans,opp[MN]={0,4,5,6,1,2,3};
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
struct matrix{
    ll g[7][7];
    void clear(){memset(g,0,sizeof(g));}
}f1,f2;
inline matrix operator * (matrix a, matrix b){
	matrix c;c.clear();
	for(int i=1; i<=6; i++) for(int j=1; j<=6; j++) for(int k=1; k<=6; k++) c.g[i][j]=(c.g[i][j]+(a.g[i][k]*b.g[k][j])%mod)%mod;
	return c;
}
inline matrix operator ^ (matrix a, ll b){
	matrix ans;ans.clear();
    for(int i=1; i<=6; i++) ans.g[i][i]=1;
	while(b){
		if(b&1) ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}
ll ksm(ll a, ll b){
    ll res=1;
    while(b){
        if(b&1) res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}
void init(){
    for(int i=1; i<=6; i++) f2.g[i][1]=1;
    for(int i=1; i<=6; i++) for(int j=1; j<=6; j++) f1.g[i][j]=mp[i][opp[j]]^1;
}
int main(){
    // freopen("1.in","r",stdin);
    n=read();m=read();
    for(int i=1; i<=m; i++){
        u=read();v=read();
        mp[u][v]=mp[v][u]=1;
    }
    init();
    matrix res=(f1^(n-1))*f2;
    for(int i=1; i<=6; i++) ans=(ans+res.g[i][1])%mod;
    ans=(ans*ksm(4,n))%mod;
    write(ans);
	return 0;
}
posted @ 2025-01-29 15:59  naroto2022  阅读(25)  评论(0)    收藏  举报