题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6415
Rikka with Nash Equilibrium
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1524 Accepted Submission(s): 626
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.
For example, when n=m=3 and matrix A is
⎡⎣⎢⎢111241131⎤⎦⎥⎥
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
Source
2018 Multi-University Training Contest 9
题意:
纳什平衡点, 所在行最大,列也是最大的, n*m的矩阵内 只有一个 纳什平衡点,
问 1-n*m的数,只出现一次,并且数字只在 1-n*m 内,问有多少种放法满足条件,
思路:
采用 dp 方法, dp[x][y][num] 代表 在 第 x 行, y列 放置数字为num 有多少中方法,
最大的数一定是 n*m , 有 n*m中方法, 倒数第二大 n*m-1 只能和 他 在一行或在一列, 否则是不行的, 有 n+m-1种方法。
倒数第三大的数字 n-m-2 根据上一个数字, 如果 n*m-1 和n*m 在一行, 那么 这个数 就有 n+2*m-2 如果在 一列 就有 2*n+m-2;
依次往下,一直到最后一个数。
如果划分 区域的 话, 把矩阵 划分成 4 块, 上下左右,
代码:
#include <bits/stdc++.h>
#include <stdio.h>
#define rep(i,a,n) for(int i = a;i<=n;i++)
typedef long long ll;
const int maxn = 82;
using namespace std;
int n,m,mod;
ll dp[maxn][maxn][maxn*maxn];
int main(int argc, char const *argv[])
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&n,&m,&mod);
dp[n][m][n*m] = 1;
for(ll num = n*m -1 ; num >=1 ;num --)
{
for(int i = n; i >=1 ;i--)
{
for(int j = m; j>=1 ;j--)
{
if( i*j < num) break; // left up corner
dp[i][j][num] = j*(n-i)%mod*dp[i+1][j][num+1]%mod; // left down corner
dp[i][j][num] = (dp[i][j][num] + i*(m-j)%mod*dp[i][j+1][num+1] )%mod; // right up corner
dp[i][j][num] = (dp[i][j][num] + (i*j-num)%mod*dp[i][j][num+1])%mod; // left down corner
}
}
}
printf("%lld\n",(n*m%mod*dp[1][1][1])%mod);
}
return 0;
}