《2018 Multi-University Training Contest 9》

这场感觉难了不少。

Rikka with Nash Equilibrium:

一开始打了个表,发现最大值放在每个位置的贡献都一样。

然后就傻傻地找每个位置的组合数规律。。

结果是DP。这真没想到。

首先,很明显,那个纳什平衡数就是n * m。

那么我们从大到小填充矩阵,如果当前用了k个数组成了i,j个那么下一个数肯定要放在这i行或者j列中。

所以dp[k][i][j] 表示放置了k个数,覆盖了i行,j列。

从三个方向转移。

1:没有行列增加,如果之前放置了k - 1个数覆盖了i行j列,那么剩下还有i * j - (k - 1)个位置可以放置。

2:增加了一行,有n - (i -1) * j个位置可以放置。

3:增加了一列,有m - (j-1) * i个位置可以放置。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
const int N = 1e5 + 5;
const int M = 1e5 + 5;
const LL Mod = 199999;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline int read(){
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

LL dp[80 * 80 + 5][85][85];//放置k个点,且已经放置了i行,j列的方案数
int main() {
    int ca;ca = read();
    while(ca--) {
        memset(dp,0,sizeof(dp));
        int n,m,mod;n = read(),m = read(),mod = read();
        dp[1][1][1] = n * m;
        for(int k = 2;k <= n * m;++k) {
            for(int i = 1;i <= n;++i) {
                for(int j = 1;j <= m;++j) {
                    if(i * j - k + 1 < 0) continue;
                    int ma1 = dp[k - 1][i][j] * (i * j - k + 1);
                    int ma2 = dp[k - 1][i - 1][j] * (n - i + 1) * j;
                    int ma3 = dp[k - 1][i][j - 1] * (m - j + 1) * i;
                    dp[k][i][j] = (dp[k][i][j] + dp[k - 1][i][j] * (i * j - k + 1)) % mod;        
                    if(i > 0) dp[k][i][j] = (dp[k][i][j] + dp[k - 1][i - 1][j] * (n - i + 1) * j) % mod;
                    if(j > 0) dp[k][i][j] = (dp[k][i][j] + dp[k - 1][i][j - 1] * (m - j + 1) * i) % mod;
                }
            }
        }
        printf("%lld\n",dp[n * m][n][m]);
    }
   // system("pause");
    return 0;
}
View Code

Rikka with Badminton:

这题题意描述真的很模糊啊。

一开始题意是参加的所有人都能打上球。。

这里的题意是选出的人里能拿出最少两个拍子,一个球来打。只需要组成一组就行了。

首先我们考虑容斥,算可以的方案数就行。

我们分类讨论:首先什么的a不用管了。没影响。

若c = 0:

  d = 0:都不行。

  d = 1:需要b != 0

  d > 1:都行。

若c != 0:

  b = 0:需要d > 1

  b = 1:需要d != 0

  b > 1:都行。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
const int N = 1e5 + 5;
const int M = 1e5 + 5;
const LL Mod = 998244353;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline int read(){
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

LL quick_mi(LL a,LL b) {
    LL re = 1;
    while(b) {
        if(b & 1) re = re * a % Mod;
        a = a * a % Mod;
        b >>= 1;
    }
    return re;
}
LL mul(LL a,LL b) {
    return a * b % Mod;
}
LL add(LL a,LL b) {
    return (a + b) % Mod;
}
int main() {
    int ca;ca = read();
    while(ca--) {
        int a,b,c,d;
        a = read(),b = read(),c = read(),d = read();
        LL n = a + b + c + d;
        LL sum = quick_mi(2,n);
        LL ma1 = (quick_mi(2,b) - 1 - b + Mod) % Mod;;//b > 1
        LL ma2 = (quick_mi(2,c) - 1) * ma1 % Mod * quick_mi(2,a + d);//c != 0,b > 1
        LL ma3 = ((quick_mi(2,c) - 1) * b % Mod * (quick_mi(2,d) - 1) % Mod * quick_mi(2,a) % Mod + Mod) % Mod;//c != 0,b = 1,d != 0
        LL ma4 = (quick_mi(2,d) - 1 - d + Mod) % Mod;//d > 1
        LL ma5 = ((quick_mi(2,c) - 1) * ma4 % Mod * quick_mi(2,a) % Mod + Mod) % Mod;//c != 0,b == 0,d > 1
        LL ans = ((ma2 + ma3) % Mod + ma5) % Mod;
        LL tmp1 = ma4 * quick_mi(2,a + b) % Mod;//c = 0,d > 1
        LL tmp2 = (d * (quick_mi(2,b) - 1) % Mod * quick_mi(2,a) % Mod + Mod) % Mod;//c = 0,d = 1,b != 0
        ans = ((ans + tmp1) % Mod + tmp2) % Mod;
        ans = (sum - ans + Mod) % Mod;
        printf("%lld\n",ans);
    }   

   // system("pause");
    return 0;
}
View Code

Rikka with Stone-Paper-Scissors:

对于胜利的期望情况,就会存在失败。

也就是说我们当前选择了用这种状态胜利,就会导致其他状态的失败。

那么对于选择一种状态的期望就是 用这种状态胜利的期望 - 用这种状态失败的期望。

例如win(a) = a * c' / (a + b + c) - a * b' / (a + b + c)

这里还需要注意一点,gcd的值可能是负数。

这样我们做除法会导致符号变换。所以要对gcd取绝对值。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
const int N = 1e5 + 5;
const int M = 1e5 + 5;
const LL Mod = 998244353;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

int main() {
    int ca;ca = read();
    while(ca--) {
        LL aa,bb,cc;aa = read(),bb = read(),cc = read();
        LL a,b,c;a = read(),b = read(),c = read();
        LL sum = a + b + c;
        LL ma1 = a * (cc - bb);
        LL ma2 = b * (aa - cc);
        LL ma3 = c * (bb - aa);
        LL ma = ma1 + ma2 + ma3;
        LL g = __gcd(ma,sum);
        g = abs(g);
        sum /= g,ma /= g;
        if(ma % sum == 0) printf("%lld\n",ma / sum);
        else printf("%lld/%lld\n",ma,sum); 
    }   

    //system("pause");
    return 0;
}
View Code

 

posted @ 2021-05-19 20:26  levill  阅读(47)  评论(0编辑  收藏  举报