【XSY3951】简单的博弈题(博弈,dp,组合数,容斥)

题面

简单的博弈题

题解

对于贪心的对手的情况,田忌赛马即可。

对于随机的对手,发现使用任何策略都不影响结果。那我们只需要选一种自己数字的排列并固定下来,再去和对手的数字的 \(m!\) 种全排列匹配即可。

暴力枚举全排列是不可接受的,考虑自己选一种特殊的数字排列固定,以优化计算。

考虑将自己的数字排序后形成的排列为 \(a_1,a_2,\cdots,a_m\),不妨设对手的数字中有 \(s_i\) 个小于 \(a_i\)

\(dp[i][j]\) 表示考虑了前 \(i\) 位,钦定我赢的次数为 \(j\),这 \(j\) 次赢的情况数。

如果上面 dp 状态的定义对于你来说比较难理解的话,相信看了下面的状态转移方程能帮助你理解:

\[\begin{aligned} &dp[0][0]=1\\ &dp[i][0]=1\qquad\operatorname{if}i\geq 1\\ &dp[i][j]=dp[i-1][j]+dp[i-1][j-1]\times (s_i-(j-1))\qquad\operatorname{if }i,j\geq 1 \end{aligned} \]

然后设 \(f[j]\) 表示考虑完前 \(m\) 位,钦定我赢的次数为 \(j\),对手的数字排列的情况数。

容易得到:

\[f[j]=(m-j)!\times dp[m][j] \]

\(g[j]\) 表示我赢的次数恰好\(j\),对手的数字排列的情况数。

易知:

\[f[w]=\sum_{i=w}^{m}\binom{i}{w}g[i] \]

那么可以得到:

\[g[w]=\sum_{i=w}^m(-1)^{i-w}\binom{i}{w}f[i] \]

而我们需要求的就是有多少种我们能赢的情况,即为:

\[\begin{aligned} ans=&\sum_{w=\frac{m+1}{2}}^{m}g[w]\\ =&\sum_{w=\frac{m+1}{2}}^{m}\sum_{i=w}^m(-1)^{i-w}\binom{i}{w}f[i]\\ =&\sum_{i=\frac{m+1}{2}}^{m}f[i]\sum_{w=\frac{m+1}{2}}^{i}(-1)^{i-w}\binom{i}{w}\\ =&\sum_{i=\frac{m+1}{2}}^{m}f[i]\binom{i-1}{\frac{m-1}{2}} \end{aligned} \]

其中最后一步用到了引理 1:

\[\sum_{j=i}^n (-1)^{j-i}\binom{n}{j}=\binom{n-1}{i-1} \]

引理 1 证明:(来自 syh 巨佬(qq:3319203781),已获得转载许可)

在证明引理 1 之前我们先有一个引理 2:

\[\binom{n}{i}=\binom{n-1}{i}+\binom{n-1}{i-1} \]

引理 2 证明:

公式化的理解:手动拆开式子然后约分。

从组合数上的意义理解:从 \(n\) 个物品中挑选出 \(i\) 个物品,相当于考虑是否最终挑选出第 \(i\) 个物品,如果不挑选出,那么方案数为 \(\dbinom{n-1}{i}\),如果挑选出,那么方案为 \(\dbinom{n-1}{i-1}\)

那么:

\[\begin{aligned} &\binom{n-1}{i-1}\\ =&\binom{n}{i}-\binom{n-1}{i}\\ =&\binom{n}{i}-\left(\binom{n}{i+1}-\binom{n-1}{i+1}\right)\\ =&\binom{n}{i}-\binom{n}{i+1}+\binom{n-1}{i+1} \end{aligned} \]

\(p_{i-1}=\dbinom{n-1}{i-1}\),那么 \(p_{i-1}=\dbinom{n}{i}-\dbinom{n}{i+1}+p_{i+1}\)

所以 \(p_{i-1}=\dbinom{n}{i}-\dbinom{n}{i+1}+\dbinom{n}{i+2}-\dbinom{n}{i+3}+\cdots\),即:

\[\dbinom{n-1}{i-1}=p_{i-1}=\sum_{j=i}^n(-1)^{j-i}\dbinom{n}{j} \]

得证。

代码如下:

#include<bits/stdc++.h>
 
#define N 10010
 
using namespace std;
 
namespace modular
{
    const int mod=998244353;
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
    inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;
 
int poww(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1) ans=mul(ans,a);
        a=mul(a,a);
        b>>=1;
    }
    return ans;
}
 
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^'0');
        ch=getchar();
    }
    return x*f;
}
 
int n,m,a[N],b[N],f[N];
int fac[N],ifac[N];
 
int C(int n,int m)
{
    if(m>n||n<0||m<0) return 0;
    return mul(mul(fac[n],ifac[n-m]),ifac[m]);
}
 
int main()
{
    n=read(),m=read();
    fac[0]=1;
    for(int i=1;i<=m;i++) fac[i]=mul(fac[i-1],i);
    ifac[m]=poww(fac[m],mod-2);
    for(int i=m;i>=1;i--) ifac[i-1]=mul(ifac[i],i);
    for(int i=1;i<=m;i++) a[i]=read();
    sort(a+1,a+m+1);
    while(n--)
    {
        int opt=read();
        for(int i=1;i<=m;i++) b[i]=read();
        sort(b+1,b+m+1);
        if(opt)
        {
            bool flag=1;
            for(int i=m/2+1,j=m;i>=1;i--,j--)
            {
                if(b[i]>a[j])
                {
                    flag=0;
                    break;
                }
            }
            printf("%d\n",flag);
        }
        else
        {
            for(int i=0;i<=m;i++) f[i]=0;
            f[0]=1;
            int tmp=0;
            for(int i=1;i<=m;i++)
            {
                while(tmp<m&&b[tmp+1]<a[i]) tmp++;
                for(int j=tmp;j>=1;j--)
                    f[j]=add(f[j],mul(f[j-1],tmp-(j-1)));
            }
            int ans=0;
            for(int i=m/2+1;i<=m;i++)
            {
                int tmp=mul(mul(f[i],fac[m-i]),C(i-1,m/2));
                if((i-m/2-1)&1) ans=dec(ans,tmp);
                else ans=add(ans,tmp);
            }
            printf("%d\n",mul(ans,ifac[m]));
        }
    }
    return 0;
}
/*
1 3
1 3 5
0 2 4 6
*/
posted @ 2022-10-30 14:26  ez_lcw  阅读(14)  评论(0编辑  收藏  举报