tags: geometry
自己畫幾張圖觀察一下三個面積的方向就會發現這很顯然
這裡簡單證明一下,不管
如果
如果
這足以證明
#include <bits/stdc++.h>
#define ff first
#define ss second
using namespace std;
using pll = pair<long long, long long>;
inline pll operator-(const pll &a, const pll &b) { return {a.ff - b.ff, a.ss - b.ss}; }
inline long long operator^(pll a, pll b) { return a.ff * b.ss - a.ss * b.ff; }
inline int sig(long long x) { return (x > 0) - (x < 0); }
void solve() {
pll p, a, b, c;
cin >> p.ff >> p.ss;
cin >> a.ff >> a.ss >> b.ff >> b.ss >> c.ff >> c.ss;
int t = sig((a-p)^(b-p)) + sig((b-p)^(c-p)) + sig((c-p)^(a-p));
if (t == 3 || t == -3) cout << "YES\n";
else cout << "NO\n";
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
tags: greedy, number theory
兩個顯然的性質
假設目前編號最大的亮燈是
實作的部分可以從大到小暴力枚舉因數操作,時間複雜度
也可以枚舉每個數的倍數求出哪些數的因數包含自己並記錄起來,時間和空間複雜度都是
一個比較乾淨的作法是從大到小枚舉每個數
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
bool sta[maxn];
void solve() {
int n, ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) cin >> sta[i];
for (int i = n; i; i--) {
for (int j = i+i; j <= n; j += i)
sta[i] ^= sta[j];
ans += sta[i];
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
solve();
return 0;
}
tags: data structures
如果把(
當)
當
(
的數量要等於)
的數量(
的數量要大於等於)
的數量於是維護前綴和
對於詢問
對於修改
暴力
維護一個區間最小區間加值線段樹
#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5 + 5;
int sum[maxn];
string str;
struct segment_tree {
static const int maxn = 16e5 + 5;
int mi[maxn] = {}, tag[maxn] = {};
inline void updata(int p, int v) { mi[p] += v, tag[p] += v; }
inline void pull(int p) { mi[p] = min(mi[p<<1], mi[p<<1|1]) + tag[p]; }
inline void push(int p) {
if (tag[p]) updata(p<<1, tag[p]), updata(p<<1|1, tag[p]);
tag[p] = 0;
}
void build(int l, int r, int p) {
if (l == r) { mi[p] = sum[l]; return; }
int mid = (l+r)>>1;
build(l, mid, p<<1), build(mid+1, r, p<<1|1);
pull(p);
}
int query(int l, int r, int ql, int qr, int p) {
if (ql == 0) return 0;
if (ql == l && qr == r) return mi[p];
push(p);
int mid = (l+r)>>1;
if (qr <= mid) return query(l, mid, ql, qr, p<<1);
else if (mid < ql) return query(mid+1, r, ql, qr, p<<1|1);
else return min(query(l, mid, ql, mid, p<<1), query(mid+1, r, mid+1, qr, p<<1|1));
}
void modify(int l, int r, int ml, int mr, int v, int p) {
if (ml == l && mr == r) { updata(p, v); return; }
int mid = (l+r)>>1;
push(p);
if (mr <= mid) modify(l, mid, ml, mr, v, p<<1);
else if (mid < ml) modify(mid+1, r, ml, mr, v, p<<1|1);
else modify(l, mid, ml, mid, v, p<<1), modify(mid+1, r, mid+1, mr, v, p<<1|1);
pull(p);
}
} seg;
void solve() {
int n, m;
cin >> n >> m;
cin >> str;
for (int i = 1; i <= n; i++)
sum[i] = sum[i-1] + 1 - 2*(str[i-1] == ')');
seg.build(1, n, 1);
int opt, l, r;
while (m--) {
cin >> opt;
if (opt == 1) {
cin >> l >> r;
if ((r-l+1)&1) cout << "NO\n";
else if (seg.query(1, n, r, r, 1) != seg.query(1, n, l-1, l-1, 1))
cout << "NO\n";
else if (seg.query(1, n, l, r, 1) - seg.query(1, n, l-1, l-1, 1) >= 0)
cout << "YES\n";
else cout << "NO\n";
}
else if (opt == 2) {
cin >> l;
if (str[l-1] == '(') {
str[l-1] = ')';
seg.modify(1, n, l, n, -2, 1);
}
else {
str[l-1] = '(';
seg.modify(1, n, l, n, 2, 1);
}
}
}
}
signed main() {
solve();
return 0;
}
tags: trees, combinatorics, math
考慮直接算出原樹的分數,用
顯然越靠近重心
現在必須算出每個
其中
只要將Subtask2的求法優化一下即可,注意到
或者換一種計算方法,全部路徑扣掉起點終點都在同一個子樹的路徑
這樣複雜度變為
#include <bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
const int maxn = 2e5 + 5;
map<long long, int> cnt;
long long fac[maxn];
vector<int> G[maxn];
int n;
long long dfs(int u, int f) {
long long ret = 1, t;
long long s = 1ll * n * (n-1) / 2;
for (int v : G[u]) {
if (v == f) continue;
t = dfs(v, u);
s -= t * (t-1) / 2;
ret += t;
}
s -= (n-ret) * (n-ret-1) / 2;
cnt[s]++;
return ret;
}
void solve() {
cin >> n;
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
G[u].emplace_back(v);
G[v].emplace_back(u);
}
dfs(1, 0);
fac[0] = 1;
for (int i = 1; i <= n; i++)
fac[i] = fac[i-1] * i % mod;
long long ans = 1;
for (pair<long long, int> p : cnt)
ans = ans * fac[p.second] % mod;
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
solve();
return 0;
}
tags: dp, math, matrices
暴力遞推
將
的線性轉移
所以轉移方程為
#include <bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
struct matrix {
static const int N = 5;
long long a[N][N] = {}, n = 0, m = 0;
matrix(int _n, int _m) : n(_n), m(_m) {}
long long* operator[](const int &x) { return a[x]; }
};
matrix operator*(matrix A, matrix B) {
int n = A.n, m = B.m, h = A.m;
matrix ret(n, m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < h; k++)
ret[i][j] = (ret[i][j] + A[i][k] * B[k][j]) % mod;
return ret;
}
matrix ksm(matrix A, long long b) {
matrix ret(A.n, A.m);
for (int i = 0; i < A.n; i++) ret[i][i] = 1;
while (b) {
if (b&1) ret = ret * A;
A = A * A;
b >>= 1;
}
return ret;
}
void solve() {
long long a1, a2, a3, x, y, n;
cin >> a1 >> a2 >> x >> y >> n;
matrix T(5, 5), v(5, 1);
T[0][0] = x*x % mod, T[0][1] = T[0][2] = x*y % mod, T[0][3] = y*y % mod;
T[1][0] = T[2][0] = x, T[1][2] = T[2][1] = y;
T[3][0] = T[4][0] = T[4][4] = 1;
a3 = (x*a2 + y*a1) % mod;
v[0][0] = a3*a2 % mod, v[1][0] = a3*a1 % mod;
v[2][0] = a2*a2 % mod, v[3][0] = a2*a1 % mod;
v[4][0] = a1*a2 % mod;
cout << (ksm(T, n-2) * v)[4][0] << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
solve();
return 0;
}
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up