2021-ICPC 网络赛第二场 F.Leapfrog

https://www.cnblogs.com/linqi05/p/15349891.html
The 2021 ICPC Asia Regionals Online Contest (II) F Leapfrog

玩酒馆战棋看到跳蛙的时候就感觉早晚要出成题目。下次可能还可以结合鼠群再出个考察数学期望的版本,就挺恐怖的。

题意题解可以看出题人的:链接。总结一下就是按t降序, b降序, a升序排序,前n-23个保持原来的位置,后23个dp解决。不理解公式或者比赛场上不能细想的话,可以把23取得稍微大一点比如 30,反正注意最大情况下不要爆 long long。

主要是po下代码,好像还没搜到有人发。感觉要注意的就是后23个dp的时候,2,3的幂次会想去用前面预处理过的fac[][],但是前面预处理的是取过模的,我们dp要比较大小肯定不能利用。感觉这是个坑点。
很久没有用博客了,代码字体看起来很丑== 见谅。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(x, l, r) for(int x = l; x <= r; x++)
#define dec(x, l, r) for(int x = l; x >= r; x--)

const int maxn = 1e5 + 5;
const int mod = 998244353;
const int N = 23;

struct node {
	int a, b, t;
	bool operator < (const node & o) {
		if(t == o.t) {
			if(b == o.b) return a < o.a;
			return b > o.b;
		}
		return t > o.t;
	}
} c[maxn];

void upd(ll &a, ll b) {
	a = max(a, b);
}

ll msm(int a, int n) {
	ll r = 1;
	while(n--) r *= a;
	return r;
}

ll dp[30][30][2], fac[2][maxn];

int main () {
	inc(i, 0, 1) {
		fac[i][0] = 1;
		inc(j, 1, 100000) fac[i][j] = fac[i][j - 1] * (i + 2) % mod;
	}
	int t;
	scanf("%d", &t);
	while(t--) {
		int n;
		scanf("%d", &n);
		inc(i, 0, n - 1) scanf("%d %d %d", &c[i].a, &c[i].b, &c[i].t);
		sort(c, c + n);
		ll res = 0;
		inc(i, 0, n - 1 - N) {
			if(c[i].t == 2) res = (res + c[i].b * fac[0][n - 1 - i]) % mod;
			else res = (res + c[i].b * fac[1][n - 1 - i]) % mod;
		}
		vector<node> v2, v3;
		inc(i, max(0, n - N), n - 1) {
			if(c[i].t == 2) v2.push_back(c[i]);
			else v3.push_back(c[i]);
		}
		memset(dp, -1, sizeof(dp));
		dp[0][0][0] = 0;
		int l = min(n, N);
		inc(i, 0, l - 1) inc(j, 0, i) inc(k, 0, 1) {
			if(dp[i][j][k] == -1) continue;
			if(i - k < l - 1) {
				int kk = l - 1 - i + k;	
				if(j < v2.size()) upd(dp[i + 1][j + 1][k], dp[i][j][k] + v2[j].b * msm(2, kk));
				if(i - j < v3.size()) upd(dp[i + 1][j][k], dp[i][j][k] + v3[i - j].b * msm(3, kk));
			} 
			if(k == 0) {
				if(j < v2.size()) upd(dp[i + 1][j + 1][1], dp[i][j][0] + v2[j].a);
				if(i - j < v3.size()) upd(dp[i + 1][j][1], dp[i][j][0] + v3[i - j].a);
			}
		}
		printf("%lld
", (res + dp[l][v2.size()][1]) % mod);
	}
}

原文地址:https://www.cnblogs.com/linqi05/p/15349891.html