首页 > 其他分享 >[赛记] csp-s模拟7

[赛记] csp-s模拟7

时间:2024-10-05 11:22:17浏览次数:1  
标签:cnt 赛记 int long low include 500005 csp 模拟

median 50pts

错解50pts(有重复的数就不行);

赛时想容斥了,其实不用容斥(好像也不能容斥)

题解做法:将每个数存一个二元组,按大小排序,枚举每一个数作为中位数,再枚举每个位置的种类,看它前面和后面有多少这些种类的数,乘起来即可;

这样就巧妙地避免了重复的情况,如果直接枚举,则有相同的数会被重复算,而这个就直接乘 $ 0 $ 了,非常巧妙;

令 $ k $ 为种类数($ k = 5 $),那么时间复杂度为: $ O(n \times k^6) $,实际情况根本跑不满,差不多 $ k^3 $ 左右;

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define int long long
const long long mod = 998244353;
int n;
int a[8][100005], qsum[500005][8], hsum[500005][8];
pair<int, int> b[1000005];
int cnt;
long long ans;
void w(int a, int bb, int c, int d, int e) {
	for (int i = 1; i <= cnt; i++) {
		if (b[i].second != c) continue;
		int o = qsum[i][a] * qsum[i][bb] % mod * hsum[i][d] % mod * hsum[i][e] % mod;
		ans = (ans + o * b[i].first % mod) % mod;
	}
}
signed main() {
	freopen("median.in", "r", stdin);
	freopen("median.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int j = 1; j <= 5; j++) {
		for (int i = 1; i <= n; i++) {
			cin >> a[j][i];
			b[++cnt] = {a[j][i], j};
		}
	}
	sort(b + 1, b + 1 + cnt);
	for (int i = 1; i <= cnt; i++) {
		for (int j = 1; j <= 5; j++) {
			qsum[i + 1][j] = qsum[i][j];
		}
		qsum[i + 1][b[i].second]++;
	}
	for (int i = cnt; i >= 1; i--) {
		for (int j = 1; j <= 5; j++) {
			hsum[i - 1][j] = hsum[i][j];
		}
		hsum[i - 1][b[i].second]++;
	}
	for (int p3 = 1; p3 <= 5; p3++) {
		for (int p1 = 1; p1 <= 5; p1++) {
			if (p1 == p3) continue;
			for (int p2 = p1 + 1; p2 <= 5; p2++) {
				if (p2 == p3) continue;
				for (int p4 = 1; p4 <= 5; p4++) {
					if (p4 == p3 || p4 == p2 || p4 == p1) continue;
					for (int p5 = p4 + 1; p5 <= 5; p5++) {
						if (p5 == p1 || p5 == p2 || p5 == p3) continue;
						w(p1, p2, p3, p4, p5);
					}
				}
			}
		}
	}
	cout << ans;
	return 0;
}

travel 0pts

赛时全输出$ Yes $ 搞了90pts,赛后绑了包0pts;

考虑题意转化,其实就是在让我们判断一个图是否有二元及以上的环或者有两个及以上的自环在同一路径上;

那么我们先用 $ Tarjan $ 缩点看一下缩点以后的点数是否等于原点数以此判断第一个,然后跑一边深搜找一下第二个即可;

时间复杂度:$ O(n + m) $;

貌似赛后数据暴搜也能过?

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
int n, m;
struct sss{
	int t, ne;
}e[2000005];
int h[2000005], cnt;
void add(int u, int v) {
	e[++cnt].t = v;
	e[cnt].ne = h[u];
	h[u] = cnt;
}
bool vis[500005], v[500005];
int vi[500005];
int dfn[500005], low[500005], dcnt;
stack<int> s;
int sum;
void Tarjan(int x) {
	dfn[x] = low[x] = ++dcnt;
	s.push(x);
	v[x] = true;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (!dfn[u]) {
			Tarjan(u);
			low[x] = min(low[x], low[u]);
		} else if (v[u]) {
			low[x] = min(low[x], dfn[u]);
		}
	}
	if (dfn[x] == low[x]) {
		sum++;
		int t = 0;
		do {
			t = s.top();
			s.pop();
			v[t] = false;
		} while(t != x);
	}
}
void afs(int x, int sum) {
	sum += vi[x];
	if (sum >= 2) {
		cout << "Yes";
		exit(0);
	}
	if (vis[x]) return;
	vis[x] = true;
	v[x] = true;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		afs(u, sum);
		vi[x] = max(vi[x], vi[u]);
	}
}
int main() {
	freopen("travel.in", "r", stdin);
	freopen("travel.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	int x, y;
	for (int i = 1; i <= m; i++) {
		cin >> x >> y;
		if(x != y) add(x, y);
		else vi[x]++;
	}
	for (int i = 1; i <= n; i++) {
		if (!dfn[i]) Tarjan(i);
	}
	if (sum != n) {
		cout << "Yes";
		return 0;
	}
	memset(v, 0, sizeof(v));
	for (int i = 1; i <= n; i++) {
		if (!v[i]) afs(i, 0);
	}
	cout << "No";
	return 0;
}

game 0pts

多测,赛时全输出 $ Yes $ 又搞了90pts。。。,赛后0pts;

打打表,或者用 mapvector 打暴力( vector 存的是状态),然后就得到结论:$ n $ 是偶数且两两相等时后手赢,否则先手赢;

至于证明:证:证毕。。。

因为有排序,所以时间复杂度:$ \Theta(Tn \log n) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int t;
int n;
int a[500005];
int main() {
	freopen("game.in", "r", stdin);
	freopen("game.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--) {
		cin >> n;
		for (int i = 1; i <= n; i++) cin >> a[i];
		if (n & 1) {
			cout << "Yes" << '\n';
			continue;
		}
		sort(a + 1, a + 1 + n);
		bool vis = true;
		for (int i = 1; i <= n; i += 2) {
			if (a[i] != a[i + 1]) {
				vis = false;
				break;
			}
		}
		if (vis) cout << "No" << '\n';
		else cout << "Yes" << '\n';
	}
	return 0;
}

标签:cnt,赛记,int,long,low,include,500005,csp,模拟
From: https://www.cnblogs.com/PeppaEvenPig/p/18447716

相关文章

  • [赛记] csp-s模拟6
    一般图最小匹配35pts纯纯的错解35pts;考虑将原数列排序,那么我们选的边就只能是相邻两个点的;发现这玩意能够递推(赛时没发现),所以直接$DP$,设$f_{i,j}$表示当前考虑到第$i$位,有$j$条边被选的最小权值,转移时考虑第$i$个点连不连第$i-1$个点即可;时间复杂......
  • 冲刺 CSP 联训模拟2
    题面温馨提示代码中的变量名可能与题意、题解不同。代码不删缺省源,可以直接拿来对拍。T1挤压Solution众所周知,异或是一种按位运算,不好进行十进制的数间合并。我们考虑将每个数拆分为二进制的形式进行处理。此时,对于每一种情况,假设表示\(2^i\)二进制位的值为\(b_i\),我......
  • 冲刺 CSP 联训模拟 2
    T1挤压概率期望,二进制拆位看到异或想到拆位算贡献\[\begin{aligned}ans&=\sum_xx^2P(x)\\&=\sum_x(b_1+b_2+...+b_{30})^2P(x)\\\(b_i表示\x\二进制下\i\位的值)\\&=\sum_x(b_1b_1+b_1b_2+...b_{30}b_{29}+b_{30}b_{30})P(x)\\&=\sum_i^{30}\sum_j^{30......
  • 代码源CSP-S模拟赛Day7-9赛后总结
    代码源CSP-S模拟赛Day7-9赛后总结Day7赛时先扫一遍题,T1显然数位dp,感觉放在T1应该不难,而且题面有一种很亲切的感觉,感觉很可做。T2简单思考一下发现最终合成的数就是\(a_1\),\(a_2\),\(a_3\)……,\(a_n\)这n个数填正负号再加上一个k的倍数,估计会有一些比较智慧的手法,感觉很......
  • CSP-S 模拟赛34
    CSP-S模拟赛34T1考虑对原序列将\(k\)的左右分成两个序列。simple的想法是分别从\(1\)开始跑前缀和,每一次总跑到下一个小于它的点,然后依次类推。发现这样做碰到序列最小值之后难以继续。然而我们发现这样跑点的过程从前往后和从后往前是等价的。这样考虑的原因是发现这样......
  • CSP-S 模拟赛 32
    CSP-S模拟赛32rnk25,\(0+0+9+0=9\)。T1[CF1578K]KingdomofIslands还没改出来。T2[CF1578L]Labyrinth警钟嚼烂:改代码改干净。首先考虑如果从\(a\)走到\(b\),人最胖是多少。毫无疑问,这是一个最大生成树问题。在这个基础上考虑原问题,我们发现由于人会越来越胖,一定有边......
  • 比赛记录(51~60)
    51CSP-S模拟赛321得分题目T1T2T3T4总分得分\(4\)\(20\)\(11\)\(27\)\(62\)排名:rank\(9\)。真正炸裂的一集。2题解T1考虑到边数较少,于是考虑能不能枚举边相关信息。通过部分分可以有如下讨论:\(c_u\nec_v\)时,意味着原先两点间有的边没了,那么两......
  • CSP-S模拟赛20241004
    A你考虑可以把这个数组当中的每个数表示成另一种形式:\(a_i=k_i\timesx+b\)(其中\(x\)是模数,\(b\)为余数)。对于求两个数是否对于某个余数同余,显然你要判断他们两个的差,即\(a_i-a_j\),那么我们用上面那种形式表示其实就是\(a_i-a_j=(k_i-k_j)\timesx\),所以你要判断整个数......
  • CSP-JS多省分数线分析!复赛如何准备?(附复赛流程视频)
    截止目前已经有多个省份CSP-JS的分数线已经出了,很多省份比去年提升了不少,像河南等地都提升了20多分,不过也有一些省份,天津比去年提升分数却不是很多。还有很多省份分数线没出,各位家长想要预估是否能够晋级的,以下是已出分数线省份表格统计:目前已出分数线省份省份入门组......
  • [CSP-J 2023] 小苹果(apple)-----------用数组
    1#include<iostream>2usingnamespacestd;3intmain(){4intn,m;5cin>>n>>m;6intg=n,t=0,li,s[n+1],b;7for(inti=1;i<=n;i++){8s[i]=i;9}10while(g){11t+=1,b=0,li=0,g-=(g+......