Codeforces
签到题
Codeforces
给出 8 8 8 个点,判断这 8 8 8 个点是否组成一个正方体。
8 8 8 个点两两组对得 28 28 28 条边,判断这 28 28 28 条边是否有 12 12 12 个相等的 A A A (楞长), 12 12 12 个相等的 B B B (正方形的对角线), 4 4 4 个相等的 C C C (正方体的对角线),且 A 2 + B 2 = C 2 A^2+B^2=C^2 A2+B2=C2 。若是,则是正方体,否则不是。
#include
#define _for(i, a) for(int i = 0, le = (a); i < le; ++i)
#define _rep(i, a, b) for(int i = (a), le = (b); i <= le; ++i)
typedef long long LL;
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
LL read() {
LL x(0), f(1); char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
struct poi {
int x, y, z;
poi(){}
poi(int x, int y, int z):x(x), y(y), z(z) {}
void sc() {
x = read(), y = read(), z = read();
}
bool operator<(const poi b) const {
if(x != b.x) return x < b.x;
if(y != b.y) return y < b.y;
if(z != b.z) return z < b.z;
return 0;
}
};
int T;
vector<poi> a;
LL getDis(poi a, poi b) {
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z);
}
int sol() {
_for(i, 8) _for(j, i) if(!(a[i] < a[j]) && !(a[j] < a[i])) return 0;
vector<LL> diss;
_for(i, 8) _for(j, i) diss.push_back(getDis(a[i], a[j]));
sort(diss.begin(), diss.end());
_for(i, 12) _for(j, i) if(diss[i] != diss[j]) return 0;
_for(i, 12) _for(j, i) if(diss[12 + i] != diss[12 + j]) return 0;
_for(i, 4) _for(j, i) if(diss[24 + i] != diss[24 + j]) return 0;
if(diss[0] + diss[12] != diss[24]) return 0;
return 1;
}
int main() {
// freopen("in.txt", "r", stdin);
scanf("%d", &T);
_for(i, T) {
a.resize(8);
_for(i, 8) a[i].sc();
printf("%s\n", sol() ? "YES":"NO");
}
return 0;
}
Codeforces
给出一个蜂窝状的地图。有 n n n 轮,两种操作。
先把每个格子映射成一个编号,之后就可以利用编号维护并查集。
维护连通块的大小和连通块内共享的边的个数。
选出格子时,查看周围一圈曾经选过的格子,使他的祖先指向此回合所选的格子,并更新连通块大小和连通块内共享的边的个数。
计算格子时,输出连通块 s i z e ∗ 6 − size* 6\ - size∗6 − 共享的边 ∗ 2 *2 ∗2 即可。
#pragma GCC optimize(3, "Ofast", "inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include
#define getchar() (S == T && (T = (S = BB) + fread(BB, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
char BB[1 << 20], *S = BB, *T = BB;
#define m_p make_pair
#define p_i pair<int, int>
#define _for(i, a) for (int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for (int i = (a), lennn = (b); i <= lennn; ++i)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"
#define mem(a, b) memset(a, b, sizeof(a))
#define mem0(a) memset(a, 0, sizeof(a))
#define fil(a, b) fill(a.begin(), a.end(), b);
#define scl(x) scanf("%lld", &x)
#define sc(x) scanf("%d", &x)
#define pf(x) printf("%d\n", x)
#define pfl(x) printf("%lld\n", x)
#define abs(x) ((x) > 0 ? (x) : -(x))
#define PI acos(-1)
#define lowbit(x) (x & (-x))
#define dg if (debug)
#define nl(i, n) (i == n - 1 ? "\n" : " ")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
typedef long long LL;
// typedef __int128 LL;
typedef unsigned long long ULL;
const int maxn = 500005;
const int maxm = 1000005;
const int maxp = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-8;
const double e = 2.718281828;
int debug = 0;
inline LL read() {
LL x(0), f(1); char ch(getchar());
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
struct poi {
int x, y;
poi(){}
poi(int x, int y):x(x), y(y) {}
bool operator<(const poi &b) const {
if(x != b.x) return x < b.x;
else return y < b.y;
}
};
struct ope {
int op, x, y;
ope(){}
ope(int op, int x, int y):op(op), x(x), y(y) {}
};
map< poi, int > toNum;
// map< int, poi > toPoi;
int f[maxn];
vector<ope> opes;
int n;
int cnt;
int num[maxn], wal[maxn];
map<poi, int> vis;
int dir[6][2] = {0, 1, 1, 0, 0, -1, -1, 0, -1, 1, 1, -1};
void init() {
}
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
void sol() {
init();
_for(i, n) {
int op = read(), x = read(), y = read();
opes.push_back(ope(op, x, y));
poi p = poi(x, y);
if(!toNum.count(p)) toNum[p] = cnt++;
}
dg for(auto i : toNum) printf("%d\t%d:\t%d\n", i.first.x, i.first.y, i.second);
_for(i, cnt) f[i] = i;
for(ope i : opes) {
poi now = poi(i.x, i.y);
int nowId = toNum[now];
if(i.op == 1) {
vis[now] = 1;
++num[nowId];
_for(k, 6) {
int x = i.x + dir[k][0], y = i.y + dir[k][1];
poi tar = poi(x, y);
if(!vis.count(tar)) continue;
int tarId = toNum[tar];
if(find(nowId) != find(tarId)) {
num[nowId] += num[find(tarId)];
wal[nowId] += wal[find(tarId)];
f[find(tarId)] = nowId;
}
++wal[nowId];
}
dg printf("x,y:(%d,%d)\tnum:%d\twal:%d\n", i.x, i.y, num[nowId], wal[nowId]);
}
else {
int der = find(nowId);
dg outval(der);
printf("%d\n", num[der] * 6 - wal[der] * 2);
}
}
}
int main() {
// ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// debug = 1;
#endif
time_t beg, end;
if (debug) beg = clock();
n = read();
sol();
if (debug) {
end = clock();
printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
}
return 0;
}
Codeforces
有 n n n 个地点由 m m m 条边相连,第 i i i 个个地点有价值 a [ i ] a[i] a[i] 的宝藏,初始时主角 V V V 在编号为 1 1 1 的地点,他拿到第 i i i 个地点的宝藏花费的时间是 d i s ( 1 , i ) ∗ 2 dis(1,i)*2 dis(1,i)∗2 。
分别计算出 [ 1 , T ] [1,T] [1,T] 时间内 V V V 能拿到的宝藏价值之和。
注意有自环和重边。
对编号 1 1 1 求最短路,之后多重背包求解最大值,背包大小为 T T T,然后一次输出 d p dp dp 数组即可。
#include
#define _for(i, a) for (int i = 0, le = (a); i < le; ++i)
#define _rep(i, a, b) for (int i = (a), le = (b); i <= le; ++i)
typedef long long LL;
#define INF 0x3f3f3f3f
const int N = 3007;
using namespace std;
LL read() {
LL x(0), f(1);
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
vector<int> G[N];
int a[N];
int dis[N];
int vis[N];
int dp[N];
struct node {
int u, w;
friend bool operator<(node a, node b) { return a.w > b.w; }
};
int n, m, T;
void Dijkstra() {
priority_queue<node> q;
_rep(i, 1, n) dis[i] = 0x3f3f3f3f;
q.push(node{1, 0});
dis[1] = 0;
memset(vis, 0, sizeof vis);
while (!q.empty()) {
node t = q.top();
q.pop();
vis[t.u] = 1;
int u = t.u;
int w = t.w;
for (auto v : G[u]) {
if (!vis[v] && dis[v] > w + 1) {
dis[v] = w + 1;
q.push(node{v, dis[v]});
}
}
}
}
int main() {
n = read(), m = read(), T = read();
_rep(i, 2, n) a[i] = read();
_rep(i, 1, m) {
int u = read(), v = read();
if (u == v) continue;
G[u].push_back(v);
G[v].push_back(u);
}
Dijkstra();
_rep(i, 1, n) {
for (int j = dis[i] * 2; j <= T; ++j) {
dp[j] = max(dp[j], dp[j - dis[i] * 2] + a[i]);
}
}
_rep(i, 1, T) printf("%d%s", dp[i], (i == T ? "\n" : " "));
return 0;
}
Codeforces
题意貌似出锅了,本来应该是签到题的。
判断第 1 1 1 个字母是否重复出现即可。
Codeforces
A A A 和 B B B 玩游戏,游戏一共有 n n n 个回合,每回合 A A A 随机选出一个 [ 1 , 20 ] [1,20] [1,20] 的数字 x x x 。 B B B 采取最优策略,在不知道 A A A 选的数字的情况下选出一个 [ 1 , 20 ] [1,20] [1,20] 的数字 y y y 。
每回合执行以下操作:
输出 A A A 能获得的分数的期望值。
由于每回合之间互不影响,所以可以先算出一个回合的得分期望值,然后乘以 n n n 即可。
枚举 B B B 的所有选择,每个选择可以算出一个得分期望值,从中选出一个最大的作为 B B B 的每回合的选择。
计算后发现无论 B B B 怎么选,得分期望都是 0 0 0 。所以答案就是0.0000。直接输出即可。