P9174 [COCI 2022/2023 #4] Bojanje

洛谷

题目要求我们求出至少有 \(k\) 个不同颜色的概率。

处理概率问题很容易想到 dp 处理,并且问题中的 \(n\) 很小,但是转移次数 \(t\) 很大,明显是一个矩阵乘法优化 dp 的问题。

那么方法有了就可以考虑转移式了。

如果按照常规的思路,以 \(dp_i\) 表示包含 \(i\) 种不同颜色的概率明显是不行的,因为有 \(i\) 种不同颜色其中包含了多种情况,并且其中的每一种情况转移到另一种情况概率不一定是相同的,而且这些不同的情况分布并不均匀,所以无法直接得到答案。

那么既然在一个状态里面含有多种情况,那么我们完全可以把这个状态拿出来。

我们给每种情况记录一个编号,开始时先处理出每一种可以转移到的情况,然后继续搜索,将转移方式记录到矩阵中。

最后直接矩阵快速幂即可。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int n,t,k,ys,id,a[15],b[15];
map<int,int> mp;
bool vis[55];
vector<int> ans;
struct MT{
	int n,m,c[55][55];
	MT(){
		memset(c,0,sizeof(c));
		n=m=0;
	}
	MT friend operator*(MT a,MT b){
		MT c;
		c.n=a.n,c.m=b.m;
		for(int i=1;i<=a.n;i++){
			for(int j=1;j<=b.m;j++){
				for(int k=1;k<=a.m;k++){
					c.c[i][j]+=a.c[i][k]*b.c[k][j]%mod;
					c.c[i][j]%=mod;
				}
			}
		}
		return c;
	}
}be,base;
void jzksm(int b){
	while(b){
		if(b&1)be=be*base;
		base=base*base;
		b>>=1;
	}	
}
int ksm(int a,int b){
	int x=a,s=1;
	while(b){
		if(b&1)s=(s*x)%mod;
		x=(x*x)%mod;
		b>>=1;
	}
	return s;
}
void bfs(){
	queue<int> q;
	int s=0;
	for(int i=1;i<=n;i++)s=s*11+1;
	q.push(s);
	mp[s]=1;
	id=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		if(vis[mp[u]])continue;
		vis[mp[u]]=1;
		int tmp=u,sum=0;
		for(int i=1;i<=n;i++)a[i]=tmp%11,tmp/=11;
		for(int i=1;i<=n;i++)if(a[i])sum++;
		if(sum>=k)ans.push_back(mp[u]);
		for(int i=1;i<=n;i++){
			if(!a[i])continue;
			for(int j=1;j<=n;j++){
				if(!a[j])continue;
				for(int k=1;k<=n;k++)b[k]=a[k];
				b[i]--,b[j]++;
				sort(b+1,b+n+1);
				int s=0;
				for(int k=n;k>=1;k--)s=s*11+b[k];
				if(mp[s])base.c[mp[u]][mp[s]]+=a[i]*a[j]%mod;
				else {
					mp[s]=++id;
					q.push(s);
					base.c[mp[u]][id]+=a[i]*a[j]%mod;
				}
			}
		}
	}
}
signed main(){
	cin>>n>>t>>k;
	ys=ksm(n*n,mod-2);
	bfs();
	be.n=1,be.m=id;
	be.c[1][1]=1;
	base.n=base.m=id;
	for(int i=1;i<=id;i++){
		for(int j=1;j<=id;j++){
			base.c[i][j]=base.c[i][j]*ys%mod;
		}
	}
	jzksm(t);
	int res=0;
	for(int i:ans){
		res+=be.c[1][i];
		res%=mod;
	}
	cout<<res;
	return 0;
}

posted @ 2025-12-07 13:09  huhangqi  阅读(3)  评论(0)    收藏  举报