【HDU - 5245 】Joyful(概率dp)

本文介绍了一种算法,用于解决在随机选取矩形区域进行涂色时,预期有多少个单元格会被涂色的问题。通过计算每个单元格不被涂色的概率,并以此推导出在多次操作后,单元格被涂色的期望次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sakura has a very magical tool to paint walls. One day, kAc asked Sakura to paint a wall that looks like an M×NM×N matrix. The wall has M×NM×N squares in all. In the whole problem we denotes (x,y)(x,y) to be the square at the xx-th row, yy-th column. Once Sakura has determined two squares (x1,y1)(x1,y1) and (x2,y2)(x2,y2), she can use the magical tool to paint all the squares in the sub-matrix which has the given two squares as corners. 

However, Sakura is a very naughty girl, so she just randomly uses the tool for KKtimes. More specifically, each time for Sakura to use that tool, she just randomly picks two squares from all the M×NM×N squares, with equal probability. Now, kAc wants to know the expected number of squares that will be painted eventually.

Input

The first line contains an integer TT(T≤100T≤100), denoting the number of test cases. 

For each test case, there is only one line, with three integers M,NM,N and KK. 
It is guaranteed that 1≤M,N≤500, 1≤K≤20. 

Output

For each test case, output ''Case #t:'' to represent the tt-th case, and then output the expected number of squares that will be painted. Round to integers.

Sample Input

2
3 3 1
4 4 2

Sample Output

Case #1: 4
Case #2: 8


        
  

Hint

The precise answer in the first test case is about 3.56790123.

思路:(参考博客)

求每一个点的贡献,最后累加,一个取两个对角线端点,这个矩形内部的点都会被涂色,也就是贡献要加,算不被染色的贡献会比较好算,就是枚举每个点,以这个点分割大矩形然后求出四个矩形的中所有可能的次数加和减去重复算的,就是这个点不被染色的次数,然后除总次数,就是不被染色的概率,然后求k次的,每个小矩形面积为1,所以贡献度为1。

ac代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
ll cal(ll n,ll m)
{
	return n*n*m*m;
}
int main()
{
//	freopen("out.txt","w",stdout);
	int t,tt=1;
	cin>>t;
	while(t--)
	{
		ll n,m,k;
		scanf("%lld%lld%lld",&n,&m,&k);
		double all=n*m*n*m;//两个格子,每个都有n*m种选择,这里会爆Int 
		double ot=0;
		for(int i=1;i<=n;i++)//遍历每个格子 
		{
			for(int j=1;j<=m;j++)
			{
				ll ans=0;
				ans+=cal(i-1,m);//没覆盖到点(i,j) 
				ans+=cal(n-i,m);
				ans+=cal(n,j-1);
				ans+=cal(n,m-j);
				ans-=cal(i-1,j-1);//没覆盖的并且算了两次的两次
				ans-=cal(i-1,m-j);
				ans-=cal(n-i,j-1);
				ans-=cal(n-i,m-j);
				double tmp=ans*1.0/all;//一次中没覆盖(染色)的概率 
				double tp=1;
				for(int q=0;q<k;q++)
				tp*=tmp; //k次的概率 
				ot+=1-tp;//k次后它被选中的概率,也就是他的贡献(一个格子面积为1,乘上1是贡献) 
			}
		}
		printf("Case #%d: %lld\n",tt++,(ll)(ot+0.5)); 
	}
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值