2018 Multi-University Training Contest 9

Rikka with Nash Equilibrium

题意:

  定义pure strategy Nash equilibriums为矩阵中的一个数并且该数为所在行和列的最大值。现在要求构造一个矩阵,满足【1,n*m】中的每个数出现且只出现一次在矩阵中,并且矩阵至多只有一个pure strategy Nash equilibriums。问可以构造多少个满足上述条件的矩阵?

分析:

  首先很容易想到的是从大到小放置这些值并且之后的数要放在之前的数占据的行和列上,因为在这种策略下,当前的数必定不是它所在行和列的最大值(除了n*m),那么就保证矩阵中至多出现一个pure strategy Nash equilibriums。考虑用dp【i】【j】【k】表示放置了i个数占据j行k列的方案数,不难看出当我们放置一个数后,只可能出现当前占据的行+1,当前占据的列+1或者当前占据的行和列都不变三种情况(不可能同时+1是因为前面规定了之后的数必须放在之前的数占据的行和列上),然后依次递推下去,最后答案的解就是dp【n*m】【n】【m】。

  参考博客:大佬博客

代码:

#include <queue>
#include <vector>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))

const int maxn=81;

int n,m,mod,T;

ll dp[maxn*maxn][maxn][maxn];

void add(ll& a,ll b)
{
    a+=b;
    while(a>=mod)    a-=mod;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d",&n,&m,&mod);

        cls(dp);
        dp[1][1][1]=n*m;
        for(int i=1;i<n*m;i++){
            for(int j=1;j<=n;j++){
                for(int k=1;k<=m;k++){
                    if(max(j,k)>i)  break;
                    if(!dp[i][j][k])    continue;
                    //如果行+1,首先考虑放在哪一列,然后考虑该列上一共有多少未被占据的行
                    if(j<n) add(dp[i+1][j+1][k],dp[i][j][k]*k%mod*(n-j)%mod);
                    //列同理
                    if(k<m) add(dp[i+1][j][k+1],dp[i][j][k]*j%mod*(m-k)%mod);
                    //行列都被占据的位置一共有j*k个,去掉之前放置的数的位置个数i
                    if(i<j*k)   add(dp[i+1][j][k],dp[i][j][k]*(j*k-i)%mod);
                }
            }
        }
        printf("%lld\n",dp[n*m][n][m]);
    }
    return 0;
}
View Code

Rikka with Stone-Paper-Scissors

题意:

  Yuta有a个剪刀卡片,b个石头卡片,c个布卡片,Rikka有a1个剪刀卡片,b1个石头卡片,c1个布卡片(a+b+c=a1+b1+c1),每次猜拳前Rikka都知道Yuta每种卡片的数量,在采取最优策略的条件下,问Rikka赢比赛的次数的期望是多少?

分析:

  考虑对于Rikka和Yuta对局的所有情况中,对于一方的一张卡片都会和对方的所有卡片组合(a+b+c),在这(a+b+c)种情况中,每赢一局则相当于对答案贡献了1/(a+b+c),输一局则贡献-1/(a+b+c)。那么对于总体,求出一共有多少种赢的情况和输的情况即可。

代码:

#include <map>
#include <queue>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))

const int maxn=1e5+100;

ll a[10],b[10];

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=1;i<=3;i++)   scanf("%lld",&a[i]);
        for(int i=1;i<=3;i++)   scanf("%lld",&b[i]);

        ll res=0,sum=0;
        ll win=0,lose=0;
        for(int i=1;i<=3;i++){
            sum+=a[i];
            lose=b[i]*a[i+1>3?1:i+1];
            win=b[i]*a[i-1<1?3:i-1];
            res+=win-lose;
        }
        ll gcd=__gcd(res,sum);
        res/=gcd;sum/=gcd;
        if(res>0&&sum<0){
            res=-res;
            sum=-sum;
        }
        if(res%sum==0)  printf("%lld\n",res/sum);
        else            printf("%lld/%lld\n",res,sum);
    }
    return 0;
}
View Code

Rikka with Badminton

题意:

  已知有a个学生没有球也没有拍,b个学生只有拍,c个学生只有球,d个学生有球又有拍。现在安排学生去参赛,比赛成功举办的条件是至少有两个拍和一个球,现在问一共有多少种安排方案使得比赛举办失败?

分析:

  对于每一种情况都讨论一下,最后去掉重复计算的情况。

代码:

#include <map>
#include <queue>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))

const int maxn=1e5+100;
const int mod=998244353;

int T;
ll a,b,c,d;

ll poww(ll a,ll k)
{
    ll res=1;
    while(k)
    {
        if(k&1) res=res*a%mod;
        a=a*a%mod;
        k>>=1;
    }
    return res;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    scanf("%d",&T);
    while(T--)
    {
        ll ans=1;
        scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
        ///没拍没球
        ans=(ans+poww(2,a)-1)%mod;
        ///有拍没球
        ans=(ans+(poww(2,b)-1)*poww(2,a)%mod)%mod;
        ///没拍有球
        ans=(ans+(poww(2,c)-1)*poww(2,a)%mod)%mod;
        ///有拍有球
        ans=(ans+d*poww(2,a+c)%mod+b*poww(2,a+c)%mod)%mod;
        ans=(ans-b*poww(2,a)%mod+mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/shutdown113/p/9542340.html