7.7
白天补题,晚上打了场CF;
CodeForces个人赛补题 : Training 1
B. Linear Algebra Test
传送门
map初始化了一下,结果wa了,暂时不知道为啥;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n;
ll ans;
map<int, int> mpa, mpb;
void solve() {
for (int i = 0; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
mpa[a]++;
mpb[b]++;
}
for (map<int, int>::iterator it = mpa.begin(); it != mpa.end(); it++) {
ans += mpa[it->first] * mpb[it->first];
}
printf("%lld\n", ans);
}
void init() {
ans = 0;
mpa.clear();
mpb.clear();
}
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
scanf("%d", &t);
while (t--) {
init();
scanf("%d", &n);
solve();
}
return 0;
}
于是换了一个写法就a了,只是把乘改成了加;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n;
ll ans;
map<int, int> mpa;
vector<int> B;
void solve() {
for (int i = 0; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
B.push_back(b);
mpa[a]++;
}
for(auto i : B) {
ans += mpa[i];
}
printf("%lld\n", ans);
}
void init() {
ans = 0;
mpa.clear();
B.clear();
}
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
scanf("%d", &t);
while (t--) {
init();
scanf("%d", &n);
solve();
}
return 0;
}
D. Dice Game
传送门
bfs,用一个Node来存三个值:now(当前朝上的数字),v(累积到这一步的值),stp(到这一步所用的步骤),然后枚举与当前向上数字相邻的数字(也即除了相加等于7以外的所有情况)即可,注意,如果累积的值已经出现过就没有必要入队了,因为这个bfs中先出现过的值肯定要比后出现的用的步骤更少,这里用一个vis数组来记录;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n;
bool vis[maxn];
struct Node {
int now, v, stp;
};
void bfs() {
queue<Node> q;
q.push(Node{ 1, 0, 0 });
while (!q.empty()) {
Node tmp = q.front();
q.pop();
for (int i = 1; i <= 6; i++) {
if (i == tmp.now || i + tmp.now == 7 || vis[tmp.v + i])
continue;
int v = tmp.v + i;
int now = i;
int stp = tmp.stp + 1;
vis[v] = true;
if (v == n) {
cout << stp << '\n';
return;
}
q.push(Node{ now, v, stp });
}
}
cout << -1 << '\n';
}
void solve() {
if (n == 1) {
cout << -1 << '\n';
return;
}
bfs();
}
void init() {
mms(vis, false);
}
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
cin >> n;
init();
solve();
}
return 0;
}
F. Building Numbers
传送门
贪心 + 前缀和,贪心策略如果a[i]是偶数就除二,如果是奇数就减一,这样一直到1就是build这个数字的最小步骤。然后把数组里所有数的build最小步骤存于一个前缀和查询就行;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n, q;
ll num[maxn], pre[maxn];
void solve() {
for (int i = 1; i <= n; ++i) {
ll tmp;
int cnt = 0;
cin >> tmp;
while(tmp != 1) {
if(tmp & 1) {
--tmp;
++cnt;
} else {
tmp /= 2;
++cnt;
}
}
num[i] = cnt;
pre[i] = cnt + pre[i - 1];
}
while(q--) {
int l, r;
cin >> l >> r;
cout << pre[r] - pre[l - 1] << '\n';
}
}
void init() {
pre[0] = 0;
num[0] = 0;
}
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
init();
cin >> n >> q;
solve();
}
return 0;
}
I. Move Between Numbers
传送门
最短路,跑了一个堆优化的dijkstra,存图的时候需要处理一下,把每个字符串中0~9出现的次数统计一下,然后根据题目意思建图,不过题目中已经给出了公式,直接套就行;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 250 + 5;
int n, s, e;
int dis[maxn];
int arr[maxn][maxn];
struct Edge {
int v, w;
};
vector<Edge> G[maxn];
struct Node {
int u, dis;
friend bool operator<(const Node& a, const Node& b) {
return a.dis > b.dis;
}
};
inline void AddEdge(int u, int v) {
G[u].push_back(Edge{ v, 1 });
}
void Dijkstra() {
bool vis[maxn];
for (int i = 1; i <= n; ++i) {
vis[i] = false;
dis[i] = inf;
}
dis[s] = 0;
priority_queue<Node> q;
q.push(Node{ s, 0 });
while (!q.empty()) {
Node tmp = q.top();
q.pop();
int u = tmp.u, d = tmp.dis;
if (vis[u])
continue;
else
vis[u] = true;
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i].v, w = G[u][i].w;
if (d + w < dis[v]) {
dis[v] = d + w;
q.push(Node{ v, dis[v] });
}
}
}
}
bool jdg(int a, int b) {
int cnt = 0;
for(int i = 0; i <= 9; i++) {
cnt += min(arr[a][i], arr[b][i]);
}
return cnt == 17;
}
void solve() {
for (int i = 1; i <= n; ++i) {
string str;
cin >> str;
for(int j = 0; j < 20; ++j) {
++arr[i][str[j] - '0'];
}
}
for (int i = 1; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j) {
if (jdg(i, j)) {
AddEdge(i, j);
AddEdge(j, i);
}
}
}
Dijkstra();
if(dis[e] == inf)
cout << -1 << '\n';
else
cout << dis[e] << '\n';
}
void init() {
mms(arr, 0);
for (int i = 1; i <= n; ++i) {
G[i].clear();
}
}
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
init();
cin >> n >> s >> e;
solve();
}
return 0;
}
感觉每次用map总会出一些奇奇怪怪的错误,现阶段在没有必须使用map的时候还是先不考虑map吧;
CodeForces Round #730 (Div.2)
传送门
蒟蒻的我当然还是只a了两题,还是半猜半蒙的;
A. Exciting Bets
传送门
半天没思路,看了半天找了个规律:
输出的前一个数是c = abs(a - b)
,即a和b的差值;
后面一个数min(m, n)
,m为a % c 或者 b % c
,即a或b对c取模;n为c - m
,即c减去这个模;
没有任何的推理根据,就是纯玄学的找规律;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 2e6;
ll a, b;
void solve() {
ll c = abs(a - b);
ll m = a % c, n = c - m;
cout << c << ' ' << min(m, n) << '\n';
}
signed main() {
std::ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--) {
cin >> a >> b;
if(a == b) {
cout << "0 0" << '\n';
continue;
}
solve();
}
return 0;
}
B. Customising the Track
传送门
依然是毫无根据的玄学找规律贪心,求出数列的平均值,用平均值以上的个数 * 平均值以下的个数就是正解,具体是为啥我也不知道;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 2e6;
int n;
void solve() {
ll sum = 0;
for(int i = 0; i < n; ++i) {
int num;
cin >> num;
sum += num;
}
ll ave = sum / n;
ll a = sum - n * ave;
ll b = n - a;
cout << a * b << '\n';
}
signed main() {
std::ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--) {
cin >> n;
solve();
}
return 0;
}