• 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);
    	}
    }
    
    
  • 相关阅读:
    Java 线程间通信 —— 等待 / 通知机制
    Java 线程基础
    Java 内存模型
    Java 并发机制底层实现 —— volatile 原理、synchronize 锁优化机制、原子操作
    优秀程序员的博客有哪些?
    程序员五一被拉去相亲,结果彻底搞懂了HTTP常用状态码
    【Redis破障之路】三:Redis单线程架构
    【Redis破障之路】一:强大的Redis
    MySQL提升笔记(4)InnoDB存储结构
    MySQL提升笔记(3)日志文件详解
  • 原文地址:https://www.cnblogs.com/linqi05/p/15349891.html
Copyright © 2020-2023  润新知