[hdoj6415 Rikka with Nash Equilibrium][dp]

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): 2021    Accepted Submission(s): 857


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,yAi,y  i[1,n]Ax,yAx,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(1t20), the number of the testcases.

The first line of each testcase contains three numbers n,m and K(1n,m80,1K109).

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
题意:将1 2 3....n*m填入一个n*m的矩阵中,要求最多有一个数既是它所在行的最大值又是其所在列的最大值,求方案数%k的值
题解:由于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掉

posted @ 2019-05-08 16:35  MekakuCityActor  阅读(214)  评论(0编辑  收藏  举报