[赛记] csp-s模拟7
median 50pts
错解50pts(有重复的数就不行);
赛时想容斥了,其实不用容斥(好像也不能容斥);
题解做法:将每个数存一个二元组,按大小排序,枚举每一个数作为中位数,再枚举每个位置的种类,看它前面和后面有多少这些种类的数,乘起来即可;
这样就巧妙地避免了重复的情况,如果直接枚举,则有相同的数会被重复算,而这个就直接乘
令
点击查看代码
#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
赛时全输出
考虑题意转化,其实就是在让我们判断一个图是否有二元及以上的环或者有两个及以上的自环在同一路径上;
那么我们先用
时间复杂度:
貌似赛后数据暴搜也能过?
点击查看代码
#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
多测,赛时全输出
打打表,或者用 map
套 vector
打暴力( vector
存的是状态),然后就得到结论:
至于证明:证:证毕。。。
因为有排序,所以时间复杂度:
点击查看代码
#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;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步