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.
题解:由于n*m肯定是其所在行和所在列的最大值,所以可知应该从n*m到1依次填数,保证当前所填数和之前填的数同行或者同列。dp[i][j][q]表示填完当前数之后已经有i行j列被填入数字,q=0表示当前的数填入的位置所在行之前没有被填充,q=1表示所在列之前没有被填充,q=2表示所在行和列都被填充了,可以得到转移方程(1)dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2])%k*(n*j-(i-1)*j)%k; (2)dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]+dp[i][j-1][2])%k*(m*i-i*(j-1))%k; (3)dp[i][j][2]=(dp[i][j][0]+dp[i][j][1]+dp[i][j][2])%k*((i*j)-(q-1))%k;

1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 ll dp[85][85][3];
5 int pre[85][85];
6 int main()
7 {
8 int t;
9 scanf("%d",&t);
10 while(t--){
11 int n,m,k;
12 scanf("%d%d%d",&n,&m,&k);
13 memset(dp,0,sizeof(dp));
14 dp[1][1][0]=n*m;
15 for(int q=2;q<=n*m;q++){
16 for(int i=min(n,q);i>=1;i--){
17 for(int j=min(m,q-i+1);j>=1;j--){
18 if(i*j<q-1)break;
19 dp[i][j][2]=(dp[i][j][0]+dp[i][j][1]+dp[i][j][2])%k*((i*j)-(q-1))%k;
20 dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2])%k*(n*j-(i-1)*j)%k;
21 dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]+dp[i][j-1][2])%k*(m*i-i*(j-1))%k;
22 }
23 }
24 }
25 printf("%lld\n",(dp[n][m][0]+dp[n][m][1]+dp[n][m][2])%k);
26 }
27 return 0;
28 }
View Code
注意:这道题如果不通过判断某些条件及时跳出循环就会T掉