• [ABC216H] Random Robots


    一、题目

    点此看题

    (n) 个机器人排成一排,有 (m) 个时刻,每个时刻每个机器人有 (1/2) 的概率向右走一步,有 (1/2) 的概率在原地不动。初始第 (i) 个机器人在位置 (x_i),问所有机器人不相撞的概率,答案模 (998244353)

    (nleq 10,x_i,mleq 1000)

    二、解法

    首先转成不相撞的方案数,最后再除以 (2^{nm})

    要求不相撞的方案数可以考虑一个逆序对容斥,我们枚举最终位置序列 (y_i)

    [sum_{y}(-1)^{pi(y)}prod_{i=1}^n{mchoose y_i-x_i} ]

    解释一下这个容斥,如果两个机器人重合那么我们就交换它们的操作序列,这个交换操作会使得逆序对减少 (1),其实这和 ( t LGV) 引理差不多。那么最后只会把没有逆序对的方案算进答案里,也就是所有机器人不相撞的方案数。

    现在考虑怎么计算这个容斥式子,主要问题在于确定序列 (y),由于数据范围很小可以考虑 (dp),具体来说我们最外层从小到大枚举最终位置 (y),然后考虑向状态 (s) 中加入最终位置为 (y) 的某个点,已经在集合中的最终位置都会比当前枚举的最终位置小,所以这时候很方便统计逆序对数,时间复杂度 (O(n2^nm))

    三、总结

    路径不相交问题首选逆序对容斥,然后分为两种情况:如果终点确定那么可以套用 ( t LGV) 引理;如果数据范围小那么可以 (dp) 计算容斥系数。

    状压 (dp) 也可用于确定序列问题上,只是这是时候需要多消耗 (O()值域()) 的复杂度。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int M = 2005;
    const int MOD = 998244353;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,a[M],f[M],p[1<<11],dp[1<<11];
    int qkpow(int a,int b)
    {
    	int r=1;
    	while(b>0)
    	{
    		if(b&1) r=r*a%MOD;
    		a=a*a%MOD;
    		b>>=1;
    	}
    	return r;
    }
    signed main()
    {
    	n=read();m=read();
    	for(int i=0;i<n;i++)
    		a[i]=read();
    	f[0]=dp[0]=1;
    	for(int i=1;i<=m;i++)
    		f[i]=f[i-1]*(m-i+1)%MOD*qkpow(i,MOD-2)%MOD;
    	for(int i=0;i<(1<<n);i++)
    		p[i]=__builtin_parity(i)?-1:1;
    	for(int i=0;i<=a[n-1]+m;i++)
    		for(int s=(1<<n)-1;s>=0;s--)
    			for(int j=0;j<n;j++) if(!(s&(1<<j)))
    				if(a[j]<=i && i<=a[j]+m)
    				{
    					dp[s|(1<<j)]=(dp[s|(1<<j)]
    					+p[s>>j]*dp[s]*f[i-a[j]])%MOD;
    				}
    	int ans=dp[(1<<n)-1]*qkpow((MOD+1)/2,n*m)%MOD;
    	printf("%lld
    ",(ans+MOD)%MOD);
    }
    
  • 相关阅读:
    【JZOJ5771】遨游【二分】【DFS】
    【JZOJ5773】简单数学题【数论,数学】
    【JZOJ5773】简单数学题【数论,数学】
    有效壳第2部分:成为一个剪贴板体操运动员
    具有多重选择和列表间拖拽的拖拽列表框
    将枚举绑定到下拉列表框并根据值对其排序
    一个具有子项格式的自定义绘制列表控件
    基本的c#屏幕截图应用程序
    将组合框下拉列表宽度调整为最长字符串宽度
    在应用程序中使用按钮控件
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15205953.html
Copyright © 2020-2023  润新知