首页 > 其他分享 >AtCoder Beginner Contest 216 H Random Robots

AtCoder Beginner Contest 216 H Random Robots

时间:2023-10-27 10:44:26浏览次数:38  
标签:216 AtCoder typedef Beginner ll long maxn define mod

洛谷传送门

AtCoder 传送门

下文令 \(n\) 为原题中的 \(K\),\(m\) 为原题中的 \(N\)。

首先概率转方案数,最后除 \(2^{nm}\) 即可。

考虑一个指数级暴力:枚举每个 bot 的终点 \(y_i\)(因为存在不能相交的限制,需要满足 \(y_1 < y_2 < \cdots < y_n\)),相当于为每个 bot 选一个 \((0, x_i) \to (m, y_i)\) 的路径(\((s, x)\) 表示第 \(s\) 秒坐标为 \(x\)),满足路径两两不交。

立刻想到 LGV 引理,于是有下面的式子:

\[ans = \sum\limits_{p} (-1)^{\sigma(p)} \prod\limits_{i = 1}^n e(i, p_i) \]

其中 \(\sigma(p)\) 为 \(p\) 逆序对数,\(e(i, j)\) 为从 \((0, x_i)\) 到 \((m, y_i)\) 的方案数。\(m\) 步中选 \(y_j - x_i\) 步往前走,可得 \(e(i, j) = \binom{m}{y_j - x_i}\)。

这个式子也可以用容斥来解释。如果两个 bot 的路径有交点,那么找到最后一个交点,交换它们之后的路径,发现方案数和原来相同,且 \(\sigma(p)\) 奇偶性一定改变。

也就是说我们现在需要知道所有 \(x_i\) 对应的 \(y_{p_i}\)。考虑从小到大枚举 \(y\) 做一个 dp,\(f_{S, k}\) 为当前已经确定 \(y_{p_i}\) 的所有 \(i\) 的集合为 \(S\),当前已经确定的所有 \(y_{p_i}\) 都 \(\le k\),上述式子的值。

转移枚举是否存在一个 \(i\) 使得 \(y_{p_i} = k\)。

  • 若不存在,则 \(f_{S, k} \gets f_{S, k - 1}\)。
  • 若存在,则枚举这个 \(i\)。拆贡献,把 \((-1)^{\sigma(p)}\) 分摊到每个 \(p_i\)。由于从小到大的加入过程保证了 \(y, p\) 都升序,所以这个 \(p_i\) 贡献的逆序对数即为 \([i + 1, n]\) 中已经被确定(包含在 \(S\) 中)的 \(j\) 的数量,设其为 \(t\)。那么我们有 \(f_{S, k} \gets f_{S \setminus \{i\}, k - 1} \times (-1)^t \binom{m}{k - x_i}\)。

时间复杂度 \(O(2^n (m + x_n))\)。

code
// Problem: H - Random Robots
// Contest: AtCoder - AtCoder Beginner Contest 216
// URL: https://atcoder.jp/contests/abc216/tasks/abc216_h
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 2100;
const ll mod = 998244353;
const ll inv2 = (mod + 1) / 2;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, m, a[maxn], fac[maxn], ifac[maxn], f[maxn][maxn];

inline ll C(ll n, ll m) {
	if (n < m || n < 0 || m < 0) {
		return 0;
	} else {
		return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
	}
}

void solve() {
	scanf("%lld%lld", &n, &m);
	for (int i = 0; i < n; ++i) {
		scanf("%lld", &a[i]);
		++a[i];
	}
	fac[0] = 1;
	for (int i = 1; i <= m; ++i) {
		fac[i] = fac[i - 1] * i % mod;
	}
	ifac[m] = qpow(fac[m], mod - 2);
	for (int i = m - 1; ~i; --i) {
		ifac[i] = ifac[i + 1] * (i + 1) % mod;
	}
	f[0][0] = 1;
	for (int S = 0; S < (1 << n); ++S) {
		for (int x = 1; x <= 2005; ++x) {
			f[S][x] = (f[S][x] + f[S][x - 1]) % mod;
			int t = 0;
			for (int i = n - 1; ~i; --i) {
				if ((~S) & (1 << i)) {
					continue;
				}
				f[S][x] = (f[S][x] + (t ? mod - 1 : 1) * f[S ^ (1 << i)][x - 1] % mod * C(m, x - a[i])) % mod;
				t ^= 1;
			}
		}
	}
	printf("%lld\n", f[(1 << n) - 1][2005] * qpow(inv2, n * m) % mod);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:216,AtCoder,typedef,Beginner,ll,long,maxn,define,mod
From: https://www.cnblogs.com/zltzlt-blog/p/17791230.html

相关文章

  • AtCoder Regular Contest 164 F Subtree Reversi
    洛谷传送门AtCoder传送门非常好题目。发现每个点颜色被反转的次数是固定的,为其深度(根结点深度为\(0\))。于是可以看作是,一放棋子就得到分数。那么先手取偶数层和后手取奇数层都会使先手得分,所以双方的目标都是尽可能多取偶数层的结点。考虑若一开始有偶数层的叶子,那么当前的......
  • AtCoder Beginner Contest(abc) 309
    B-Rotate题目大意给定一个n*n的矩阵,要求把矩阵的最外围按照顺时针转动一个数据,输出转动后的矩阵;解题思路数据不大,暴力即可;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#def......
  • 76th 2023/10/10 Atcoder 10/8-ARC-T3
    这道题题目很有意思,看上去是很简单明显的计数,但一思考会发现要死很多重复状态因为标记的线很容易让人从一个方框开始思考起,所以很容易带入关于重复考虑的误区观察到线是斜着的,思考影响到的范围若涂上一个格子或左一个格子的右下,则该格子不能填涂左上观察到影响范围是一个个斜......
  • python系列教程216——何时使用列表解析
    声明:在人工智能技术教学期间,不少学生向我提一些python相关的问题,所以为了让同学们掌握更多扩展知识更好地理解AI技术,我让助理负责分享这套python系列教程,希望能帮到大家!由于这套python教程不是由我所写,所以不如我的AI技术教学风趣幽默,学起来比较枯燥;但它的知识点还是讲到位的了,也值......
  • AtCoder Regular Contest 167——B - Product of Divisors
    题目很明显,给定 所有因数的积不断除以最多能除几次。首先,很容易发现,对于每一对因子,都可以对答案得出B的贡献,设A的因子数目为n。将A进行质因数分解,PBa1,PBa2,PBa3……PBam,那么因数个数就是质因子加一的乘积。那么因子对数也就是前者一半。答案就是B乘因子对数除以二注意此处......
  • AtCoder Beginner Contest(abc) 308
    B-DefaultPrice题目大意小莫买了n个寿司,现在给出m个寿司的名称和m+1个价格,如果小莫买的其中一个寿司不在这m个寿司之中就用价格m0;请问小莫买的寿司花了多少钱解题思路数据不大,暴力哈希即可;神秘代码#include<bits/stdc++.h>#defineintlonglong#define......
  • Atcoder Beginner Contest 324 G Generate Arrays 题解-Treap
    为了更好的阅读体验,请点击这里题目链接套上平衡树板子就能做的很快的题,然后因为是指针存树,因此交换只需要把序列大小较小的挨个拿出来插到相应的地方即可。复杂度\(O(N\log^2N)\)。但是一定要记住不可以直接使用std::swap交换包含带有指针的类的实例(如代码中的Treap类)!......
  • AtCoder Regular Contest 167
    Preface补一下上周日的ARC,因为当天白天和队友一起VP了一场所以就没有精力再打一场了这场经典C计数不会D这种贪心乱搞反而是一眼秒了,后面的EF过的太少就没看A-ToastsforBreakfastParty用一个类似于蛇形的放法就好了,比如对于\(n=9,m=5\),放法为:567894321#includ......
  • Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginner Contes
    JapanRegistryServices(JPRS)ProgrammingContest2023(AtCoderBeginnerContest324)赛后总结可悲的是:我没来得及写题解。T1Same秒切。直接输入排一遍序再遍历即可。#include<bits/stdc++.h>usingnamespacestd;intn,a[101];intmain(){cin>>n;f......
  • 比赛总结:Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginn
    比赛:JapanRegistryServices(JPRS)ProgrammingContest2023(AtCoderBeginnerContest324)A-same1.常规方法intmain(){ intn; cin>>n; vector<int>s(n);//利用vector容器可以不需要确定内存大小 for(auto&n:s) { cin>>n; } for(inti=0;i......