• 【比赛】【校内测试】2020-7-19校内测试


    2020-7-19校内测试总结+题解。

    比赛链接

    点击打开链接

    比赛经历

    打开A题,发现是个辛普森积分,但是我并没学辛普森积分,所以跳了。

    打开B题,发现是个组合计数,跳了

    打开C题,感觉是个贪心题。

    继续看C,感觉像个网络流贪心之类的。但是越想越不对劲,然后发现是个sb dp题。码量一发,交了。

    看B题,发现可以考虑使用组合数直接推式子,得到了 60 分的做法。接着想,发现啥都想不出来。感觉是个卷积形式,但是没啥用。于是就不知道该想什么了。莫名就10:30了。

    再看A题,可以写两个部分分。然后看B题,想起来打表找规律,但是时间不够了。

    预估得分:20+60+100. 与实际得分无偏差。

    感觉失误在于第二题“于是就不知道该想什么了”,可能并不完全是不知道该想什么了,是因为感觉式子很麻烦,懒得写出来了。只是举了个例子观察例子,却没有把式子的形式写出来,但这就无法继续推式子了。下次一定不要怕麻烦!

    考完之后发现人均打表找规律切T2。

    (一)-小Q 的等离子场

    题目解法

    使用自适应辛普森积分即可。

    代码

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef double db;
    const int MAXN = 205, MAXR = 1e4 + 5;
    const db inf = 1e8, lim = 1e4, eps = 1e-8;
    int n, tot;
    db x[MAXN], y[MAXN], r[MAXN], R[MAXN];
    struct Region {
    	db ps;
    	int tag;
    	Region() {}
    	Region(db _p, int t) : ps(_p), tag(t) {}
    } store[MAXN * 4];
    bool cmp(Region x, Region y) { return x.ps < y.ps; }
    pair<db, db> cross(db x, db y, db r, db ps) {
    	if (ps < x - r || ps > x + r)
    		return make_pair(inf, inf);
    	db a = abs(ps - x), len = sqrt(r * r - a * a);
    	return make_pair(y - len, y + len);
    }
    db f(db p) {
    	tot = 0;
    	for (int i = 1; i <= n; ++i) {
    		pair<db, db> tmp1 = cross(x[i], y[i], R[i], p), tmp2 = cross(x[i], y[i], r[i], p);
    		if (tmp1.first <= lim && tmp2.first <= lim) {
    			store[++tot] = Region(tmp1.first, 1);
    			store[++tot] = Region(tmp2.first, -1);
    			store[++tot] = Region(tmp2.second, 1);
    			store[++tot] = Region(tmp1.second, -1);
    		} else if (tmp1.first <= lim && tmp2.first > lim) {
    			store[++tot] = Region(tmp1.first, 1);
    			store[++tot] = Region(tmp1.second, -1);
    		}
    		//特判 
    	}
    	sort(store + 1, store + tot + 1, cmp);
    	db ret = 0;
    	int sum = 0;
    	for (int i = 1; i < tot; ++i) {
    		db len = store[i + 1].ps - store[i].ps;
    		sum += store[i].tag;
    		if (sum)
    			ret += len;
    	}
    	return ret;
    }
    db simpson(db a, db b) {
    	db mid = (a + b) * 0.5;
    	return (b - a) * (f(a) + f(b) + 4.0 * f(mid)) / 6.0;
    }
    db cal(db x, db y, db ans) {
    	db mid = (x + y) * 0.5;
    	db lv = simpson(x, mid), rv = simpson(mid, y);
    	if (fabs(lv + rv - ans) < 15.0 * eps)
    		return lv + rv + (lv + rv - ans) / 15.0;
    	else
    		return cal(x, mid, lv) + cal(mid, y, rv);
    }
    int main() {
    	scanf("%d", &n);
    	double lp = inf, rp = -inf;
    	for (int i = 1; i <= n; ++i) {
    		scanf("%lf%lf%lf%lf", &x[i], &y[i], &R[i], &r[i]);
    		lp = min(lp, x[i] - R[i]);
    		rp = max(rp, x[i] + R[i]);
    	}
    	printf("%.3lf
    ", cal(lp, rp, simpson(lp, rp)));
    	return 0;
    }
    

    (二)-小Z的城市之旅

    题目解法

    可以发现,上-下,左-右所得的结果固定则最终到达的点固定。可以通过最终的x坐标,最终的y坐标,总步数列出三个四元方程,有一个数不确定,那么枚举那个数然后计算即可。

    但是这样复杂度是 (mathcal O(Tn)) 的,很明显过不去。我们发现式子的形式是类似这样的:

    [sum_k inom{r}{m+k} inom{s}{n-k} ]

    发现这是个范德蒙德卷积。所以套用式子即可。

    [sum_k inom{r}{m+k} inom{s}{n-k}=inom{r+s}{m+n} ]

    如何证明:发现这是个卷积的形式。考虑使用生成函数:(inom{r}{k}) 的生成函数是 (f(x)=(1+x)^r)(g(x)=(1+x)^s),那么等式左侧就相当于 ([x^{m+n}]f(x)cdot g(x)) 。也就是 ([x^{m+n}](1+x)^{r+s}=inom{r+s}{n+m})

    总结

    • 范德蒙德卷积。

    代码

    #include <cstdio>
    using namespace std;
    typedef long long ll;
    const int CN = 2e5 + 5, Mod = 998244353, N = 2e5;
    int ml(int x, int y) { return (ll) x * y % Mod; }
    int ad(int x, int y) { return (x + y > Mod) ? (x + y - Mod) : (x + y); }
    int ksm(int x, int y) {
    	int ret = 1;
    	for (; y; y >>= 1, x = ml(x, x))
    		if (y & 1) ret = ml(ret, x);
    	return ret;
    }
    int T, r, fac[CN << 1], ifac[CN << 1];
    ll x, y;
    void Init() {
    	fac[0] = ifac[0] = 1;
    	for (int i = 1; i <= 2 * N; ++i) fac[i] = ml(fac[i - 1], i);
    	for (int i = 1; i <= 2 * N; ++i) ifac[i] = ksm(fac[i], Mod - 2);
    }
    int binom(int x, int y) {
    	if (x < 0 || y < 0 || x < y) return 0;
    	return ml(fac[x], ml(ifac[y], ifac[x - y]));
    }
    int main() {
    	scanf("%d", &T);
    	Init();
    	while (T--) {
    		scanf("%lld%lld%d", &x, &y, &r);
    		if (x > r || y > r || ((x + y + r) % 2 == 1)) {
    			printf("0
    ");
    			continue ;
    		}
    		printf("%d
    ", ml(binom(r, (r - x - y) / 2), binom(r, (r - x - y) / 2 + x)));
    	}
    	return 0;
    }
    

    (三)-小H的硬币游戏

    题目解法

    容易发现模 (k) 余数不同的位置没有关系,所以按模 (k) 的余数分类,然后 dp 即可(类似最大独立集那种 dp)。

    代码

    #include <cstdio>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const int CN = 1e5 + 5, inf = 1e9;
    int N, K, a[CN];
    ll ans, f[CN][2];
    int main() {
    	scanf("%d%d", &N, &K);
    	for (int i = 1; i <= N; ++i)
    		scanf("%d", &a[i]);
    	for (int i = 1; i <= K; ++i) {
    		int cnt = 0;
    		f[0][0] = 0;
    		f[0][1] = -inf;
    		for (int j = i; j <= N - K; j += K) {
    			++cnt;
    			f[cnt][0] = f[cnt][1] = -inf;
    			f[cnt][0] = max(f[cnt - 1][0], f[cnt - 1][1]);
    			f[cnt][1] = f[cnt - 1][0] + a[j] + a[j + K];
    		}
    		ans += max(f[cnt][0], f[cnt][1]);
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    GGEditor
    Vue 项目(HTML5 History 模式) 部署服务器
    mysql连接状态
    mysql连接状态
    HBase配置性能调优
    HBase配置性能调优
    spark streaming检查点使用
    spark streaming检查点使用
    spark streaming的有状态例子
    spark streaming的有状态例子
  • 原文地址:https://www.cnblogs.com/YouthRhythms/p/13347745.html
Copyright © 2020-2023  润新知