6415 Rikka with Nash Equilibrium
http://acm.hdu.edu.cn/showproblem.php?pid=6415
题意:已知n, m, k,求仅有一个 pure strategy Nash equilibriums(六花选行号, 勇太选列号,对应数字即为结果,psne即对于当前矩阵,两人都无法通过单独改变自己的选择增大结果)的n*m矩阵有几种,答案模k。
(1. Each integer in [1,nm] occurs exactly once in A.
2. The game has at most one pure strategy Nash equilibriums.)
思路:dp[i][j][k]表示(从大到小)放置第i个数字于某j行k列合法。
其中,dp[1][1][1] = (n*m) , i|2...n*m, j|1...n, k|1...m;
j*k > i-1时有如下
dp[i][j][k] = (dp[i-1][j-1][k] * k * (n-j+1)//贡献一个额外的可行列, 可行列k*可行列上未使用行(n -(j-1))。
+ dp[i-1][j][k-1] * j * (m-k+1)//同上。
+ dp[i-1][j][k] * (j*k - (i-1))//无贡献(置于交叉点上), j*k个可行交叉点 - (i-1)个已使用交叉点。
ps:中途转long long每次只取一次模可大大减少耗时。
1 #include <iostream> 2 #include <stdio.h> 3 #include<algorithm> 4 #include <iostream> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <math.h> 9 #include <time.h> 10 #include <vector> 11 #include <bitset> 12 #include <queue> 13 #include <map> 14 #include <set> 15 using namespace std; 16 17 typedef long long ll; 18 const int N = 80+5; 19 int dp[N*N][N][N]; 20 21 int main() 22 { 23 int t; 24 scanf("%d",&t); 25 while(t--){ 26 int n, m, mod; 27 scanf("%d%d%d", &n, &m, &mod); 28 dp[1][1][1] = n*m%mod; 29 for(int i = 2; i <= n*m; i++){ 30 for(int j = 1;j <= n; j++){ 31 for(int k = 1;k <= m; k++){ 32 if(j*k > i-1){ 33 dp[i][j][k] = 1ll*dp[i-1][j-1][k] * k * (n-j+1)%mod; 34 dp[i][j][k] = (dp[i][j][k] + 1ll*dp[i-1][j][k-1] * j * (m-k+1)%mod)%mod; 35 dp[i][j][k] = (dp[i][j][k] + 1ll*dp[i-1][j][k] * (j*k - (i-1))%mod)%mod; 36 } 37 } 38 } 39 } 40 printf("%d ",dp[n*m][n][m]); 41 } 42 return 0; 43 }
算出样例之后就沉浸于递归的思路无法自拔,然而。。。递归->记忆化搜索->(递推?)动态规划。。。想到递归之后上手写一下记忆化搜索的话可能就想到dp了,脑速不够还不动手就很不ok。。。
就算不推dp,直接记忆化搜索也能过,啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊。。。为啥窝不写啊啊啊啊啊啊啊啊啊啊啊啊啊。。。总是拿窝的算法太暴力当借口不写题到最后毛都不会。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll mod,n,m; 5 const ll N=6405; 6 ll dp[85][85][85*85]; 7 ll dfs(ll x,ll y,ll z){//占领了x行,y列。已经放进去了z个数字 8 if(dp[x][y][z]!=-1) return dp[x][y][z]; 9 ll tmp=0; 10 if(x<n) tmp=(tmp+y*(n-x)%mod*dfs(x+1,y,z+1))%mod; 11 if(y<m) tmp=(tmp+x*(m-y)%mod*dfs(x,y+1,z+1))%mod; 12 if(x*y>z) tmp=(tmp+(x*y-z)%mod*dfs(x,y,z+1))%mod; 13 return dp[x][y][z]=tmp; 14 } 15 int main() 16 { 17 ll t; 18 scanf("%lld",&t); 19 while(t--){ 20 memset(dp,-1,sizeof(dp)); 21 scanf("%lld%lld%lld",&n,&m,&mod); 22 dp[n][m][n*m]=1; 23 ll ans=m*n%mod*dfs(1,1,1)%mod; 24 printf("%lld ",ans); 25 } 26 }
(但是真的很慢,4000+ms卡过。)
hdu 6406 Taotao Picks Apples
思路:二分吖upper_bound吖~模拟吖!!!(手残党,WA地一声哭出来。)
1 #include <iostream> 2 #include <stdio.h> 3 #include<algorithm> 4 #include <iostream> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <math.h> 9 #include <time.h> 10 #include <vector> 11 #include <bitset> 12 #include <queue> 13 #include <map> 14 #include <set> 15 using namespace std; 16 17 typedef long long ll; 18 const int N = 1e5+5; 19 int a[N], premax[N], tmp[N], vis[N], t, n, m, l; 20 vector <int> di[N]; 21 22 void init(){ 23 memset(a, 0, sizeof a); 24 memset(premax, 0, sizeof premax); 25 memset(tmp, 0, sizeof tmp); 26 memset(vis, 0, sizeof vis); 27 scanf("%d%d", &n,&m); 28 for(int i = 0; i <= n; i++) di[i].clear(); 29 int maxx = -1; 30 l = 0; 31 for(int i = 1; i <= n; i++){ 32 scanf("%d", &a[i]); 33 if(a[i] > maxx){ 34 vis[i] = 1; 35 maxx = premax[i] = tmp[l++] = a[i]; 36 } 37 else premax[i] = maxx; 38 } 39 int r = 0; 40 for(int i = 1; i <= n; i++){ 41 if(vis[i] == 1) r = i; 42 else{ 43 int sz = di[r].size(); 44 if(sz == 0 || (sz > 0 && a[i] > di[r][sz-1])) 45 di[r].push_back(a[i]); 46 } 47 } 48 } 49 void solve(){ 50 init(); 51 for(int i = 1, p, q; i <= m; i++){ 52 scanf("%d%d", &p,&q); 53 if(q == premax[p] || (!vis[p] && q < premax[p])) printf("%d ", l); 54 else if(!vis[p] && q > premax[p]){ 55 int x = l - (upper_bound(tmp, tmp+l, q) - upper_bound(tmp, tmp+l, premax[p])); 56 printf("%d ", x+1); 57 } 58 else if(vis[p] && q > premax[p]) 59 printf("%d ", l - (upper_bound(tmp, tmp+l, q) - upper_bound(tmp, tmp+l, premax[p]))); 60 else if(vis[p] && q < premax[p]){ 61 if(p == 1 || q > premax[p-1]) 62 printf("%d ", l + (di[p].end() - upper_bound(di[p].begin(), di[p].end(), q))); 63 else { 64 int x = di[p].end() - upper_bound(di[p].begin(), di[p].end(), premax[p-1]); 65 printf("%d ", l+x-1); 66 } 67 } 68 } 69 } 70 71 int main(){ 72 for(scanf("%d", &t); t; t--) solve(); 73 return 0; 74 }
hdu6400 Parentheses Matrix
思路:牺牲小我,拯救全家。
1 #include <iostream> 2 #include <stdio.h> 3 #include<algorithm> 4 #include <iostream> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <math.h> 9 #include <time.h> 10 #include <vector> 11 #include <bitset> 12 #include <queue> 13 #include <map> 14 #include <set> 15 using namespace std; 16 17 int main() 18 { 19 int _, h,w; 20 char ans[205][205];bool rev = 0; 21 for(scanf("%d", &_);_;_--){ 22 rev = 0; 23 memset(ans, 0, sizeof(ans)); 24 scanf("%d%d", &h,&w); 25 if((h&1) && (w&1)){ 26 for(int i = 0; i < h; i++){ 27 for(int i = 0; i < w; i++) printf("("); 28 puts(""); 29 } 30 } 31 else if((h&1) || (w&1)){ 32 if(h&1){ 33 for(int i = 0; i < h; i++){ 34 for(int j = 0; j < w; j+=2){ 35 ans[i][j] = '('; 36 ans[i][j+1] = ')'; 37 } 38 } 39 } 40 else if(w&1){ 41 for(int i = 0; i < w; i++){ 42 for(int j = 0; j < h; j+=2){ 43 ans[j][i] = '('; 44 ans[j+1][i] = ')'; 45 } 46 } 47 } 48 //for(int i = 0; i < h; i++) puts(ans[i]); 49 } 50 else { 51 if(h > w){ 52 swap(h, w); 53 rev = 1; 54 } 55 if(h == 2){ 56 for(int i = 0; i < w; i++){ 57 ans[0][i] = '('; 58 ans[1][i] = ')'; 59 } 60 } 61 else if(h == 4){ 62 for(int i = 0; i < w; i++) ans[0][i] = '(', ans[h-1][i] = ')'; 63 for(int i = 0; i < w/2; i++) ans[1][i] = ')', ans[2][i] = '('; 64 for(int i = w/2; i < w; i++) ans[1][i] = '(', ans[2][i] = ')'; 65 } 66 else{ 67 for(int i = 0; i < w; i++) ans[0][i] = '(', ans[h-1][i] = ')'; 68 for(int i = 1; i < h-1; i+=2) for(int j = 0; j < w; j+=2) ans[i][j] = '(', ans[i][j+1] = ')'; 69 for(int i = 2; i < h; i+=2){ 70 ans[i][0] = '('; ans[i][w-1] = ')'; 71 for(int j = 1; j < w-1; j+=2) ans[i][j] = '(', ans[i][j+1] = ')'; 72 } 73 74 } 75 } 76 if(!rev) 77 for(int i = 0; i < h; i++) puts(ans[i]); 78 else{ 79 for(int i = 0; i < w; i++){ 80 for(int j = 0; j < h; j++) 81 putchar(ans[j][i]); 82 puts(""); 83 } 84 } 85 } 86 return 0; 87 }