2018 Multi-University Training Contest 9: A. Rikka with Nash Equilibrium(DP)

 

Rikka with Nash Equilibrium

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 507    Accepted Submission(s): 210

Problem Description

Nash Equilibrium is an important concept in game theory.

Rikka and Yuta are playing a simple matrix game. At the beginning of the game, Rikka shows an n×m integer matrix A. And then Yuta needs to choose an integer in [1,n], Rikka needs to choose an integer in [1,m]. Let i be Yuta's number and j be Rikka's number, the final score of the game is Ai,j. 

In the remaining part of this statement, we use (i,j) to denote the strategy of Yuta and Rikka.

If the strategy is (1,2), the score will be 2; if the strategy is (2,2), the score will be 4.

A pure strategy Nash equilibrium of this game is a strategy (x,y) which satisfies neither Rikka nor Yuta can make the score higher by changing his(her) strategy unilaterally. Formally, (x,y) is a Nash equilibrium if and only if:

{Ax,y≥Ai,y  ∀i∈[1,n]Ax,y≥Ax,j  ∀j∈[1,m]}

In the previous example, there are two pure strategy Nash equilibriums: (3,1) and (2,2).

To make the game more interesting, Rikka wants to construct a matrix A for this game which satisfies the following conditions:
1. Each integer in [1,nm] occurs exactly once in A.
2. The game has at most one pure strategy Nash equilibriums. 

Now, Rikka wants you to count the number of matrixes with size n×m which satisfy the conditions.

Input

The first line contains a single integer t(1≤t≤20), the number of the testcases.
The first line of each testcase contains three numbers n,m and K(1≤n,m≤80,1≤K≤109).
The input guarantees that there are at most 3 testcases with max(n,m)>50.

Output

For each testcase, output a single line with a single number: the answer modulo K.

Sample Input

2 3 3 100

5 5 2333

Sample Output

64 1170

 

题意:

对于一个n*m的矩阵,如果某个位置上的数满足即是行最大值,也是列最大值,那么这个位置被称为纳什均衡点,问有多少个矩阵,满足①n行m列;②矩阵中的所有数都是1~n*m中的其中一个,且独一无二;③矩阵中最多只有一个纳什均衡点,答案对K取模

 

思路:

  1. 因为条件②,所以最大的那个数(n*m)所在位置一定是纳什均衡点
  2. 考虑从最大的数字开始填,n*m可以填在任意一个位置,总共n*m种填法
  3. 第二个数n*m-1很显然只能和最大数同一行或者同一列,共有n+m-1种情况
  4. 同理, 前两个数如果在同一行,第三个数n*m-2可以填在其中两列或者一行,共有2*n+m-2中情况,前两个数如果在同一列,第三个数n*m-2可以填在其中两行或者一列,共有n+2*m-2种情况
  5. ……

考虑dp[x][y][z]表示当前填到数字z,z只能填入其中x行y列中,如下图

状态为dp[3][4][93],意思就是当前要填数字93,只能填在前4列,前3行

  • 如果填在左上角(左上角还有5个位置),那么有转移:dp[3][4][93] += 5*dp[3][4][92];
  • 如果填在右上角,那么有转移:dp[3][4][93] += (m-4)*3*dp[3][5][92]
  • 如果填在左下角,那么有转移:dp[3][4][93] += 4*(n-3)*dp[4][4][92]
  • 不能填在右下角

总体复杂度O(n²m²)

 

#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
LL n, m, mod, dp[82][82][6450], jc[6450] = {1};
LL Sech(LL x, LL y, LL p)
{
	LL ans, now;
	if(x==n || y==m)
		return jc[p];
	if(dp[x][y][p]!=-1)
		return dp[x][y][p];
	ans = 0;
	now = x*y-(n*m-p);
	if(now>=1)
		ans = (ans+Sech(x, y, p-1)*now)%mod;
	ans = (ans+(n-x)*y*Sech(x+1, y, p-1))%mod;
	ans = (ans+(m-y)*x*Sech(x, y+1, p-1))%mod;
	dp[x][y][p] = ans;
	return ans;
}
int main(void)
{
	LL T, i;
	scanf("%lld", &T);
	while(T--)
	{
		scanf("%lld%lld%lld", &n, &m, &mod);
		for(i=1;i<=6446;i++)
			jc[i] = jc[i-1]*i%mod;
		memset(dp, -1, sizeof(dp));
		printf("%lld\n", n*m*Sech(1, 1, n*m-1)%mod);
	}
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值