A - PERFECT NUMBER PROBLEM
题意
找到前五个因数之和(除了自己)是本身的数
思路
(nsqrt n) 暴力打表
6, 28, 496, 8128, 33550336
M - Subsequence
题意
询问是否是子序列
思路
直接暴力
#include<bits/stdc++.h>
using namespace std;
int mp[26][100010];
int cnt[26];
char s[100010], p[1010];
int T;
int main() {
scanf("%s", s + 1);
int x = strlen(s + 1);
for (int i = 1; i <= x; i++) {
mp[s[i] - 'a'][cnt[s[i] - 'a']++] = i;
}
scanf("%d", &T); getchar();
while (T--) {
scanf("%s", p + 1);
int now = 0, f = 1;
int len = strlen(p + 1);
for (int i = 1; i <= len; i++) {
int idx = p[i] - 'a';
int pos = upper_bound(mp[idx], mp[idx] + cnt[idx], now) - mp[idx];
if (pos == cnt[idx]) {
f = 0;
break;
}
now = mp[idx][pos];
}
if (f)puts("YES");
else puts("NO");
}
}
H - Coloring Game
(f[n] = 2*2*3^{n-2})
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1000000007;
int qpow(int a, int p) {
int ans = 1;
while (p) {
if (p & 1)ans = (ans * a) % mod;
a = a * a % mod;
p >>= 1;
}
return ans;
}
signed main() {
int n; cin >> n;
if (n == 1)cout << 1 << endl;
else cout << 4 * qpow(3, n - 2) % mod << endl;
}
K - MORE XOR
找规律
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int A[N];
int T, n, m;
int f[N];
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", A + i);
f[i] = A[i];
if (i > 4)f[i] ^= f[i - 4];
}
scanf("%d", &m);
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
if (l == r) {
printf("%d
", A[l]);
continue;
}
int len = r - l + 1;
int ans = 0;
if (len % 2 == 0) {
int x = len / 2;
if (x % 2 == 0)ans = 0;
else ans = f[r] ^ f[l + 1] ^ A[l + 1] ^ f[r - 1] ^ f[l] ^ A[l];;
}
else {
int x = len / 2;
if (x % 2 == 0) {
ans = f[r] ^ f[l] ^ A[l];
}
else {
ans = f[r - 1] ^ f[l + 1] ^ A[l + 1];
}
}
printf("%d
", ans);
}
}
}
J - Distance on the tree
查询树上路径上边权小于等于 (k) 的边数
写的树剖加主席树,挂了
/*
* @Author: zhl
* @Date: 2020-11-9 20:36:59
*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
#define mid ((l+r)>>1)
using namespace std;
const int N = 5e5 + 10;
int A[N];
int n, m;
struct Edge {
int to, next, w;
}E[N << 1];
int head[N], tot;
void addEdge(int from, int to,int w) {
E[++tot] = Edge{ to,head[from],w };
head[from] = tot;
}
int fa[N], sz[N], Tfa[N], dep[N], son[N];
//dfs1处理dep,sz,fa,son(重儿子)
void dfs1(int u, int p) {
fa[u] = p;
dep[u] = dep[p] + 1;
sz[u] = 1;
int mx = -1;
repE(i, u) {
int v = E[i].to;
if (v == p)continue;
dfs1(v, u);
sz[u] += sz[v];
if (sz[v] > mx)mx = sz[v], son[u] = v;
}
}
int cnt;
int id[N], val[N], top[N];
//dfs2 剖分树链
void dfs2(int u, int topf, int w) {
id[u] = ++cnt;
val[cnt] = w;
top[u] = topf;
if (!son[u])return;
int x = 0;
repE(i, u)if (E[i].to == son[u]) x = E[i].w;
dfs2(son[u], topf, x);
repE(i, u) {
int v = E[i].to;
if (v == fa[u] or v == son[u])continue;
dfs2(v, v, E[i].w);
}
}
int W[N];//边权
int root[N];
int cntW;
int getid(int x) {
return lower_bound(W + 1, W + cntW + 1, x) - W;
}
int L[N << 5], R[N << 5], sum[N << 5];
int Tot;
int build(int l, int r) {
int u = ++Tot;
sum[u] = 0;
if (l < r) {
L[u] = build(l, mid);
R[u] = build(mid + 1, r);
}
return u;
}
int insert(int pre, int l, int r, int pos) {
int u = ++Tot;
L[u] = L[pre];
R[u] = R[pre];
sum[u] = sum[pre] + 1;
if (l >= r)return u;
if (pos <= mid) {
L[u] = insert(L[pre], l, mid, pos);
}
else {
R[u] = insert(R[pre], mid + 1, r, pos);
}
return u;
}
int query(int rt_x, int rt_y,int l,int r, int k) {
if (l == r) {
return sum[rt_y] - sum[rt_x];
}
int num = sum[L[rt_y]] - sum[L[rt_x]];//区间内,左半区间的数的数量
if (k <= mid) return query(L[rt_x], L[rt_y], l, mid, k);
else return num + query(R[rt_x], R[rt_y], mid + 1, r, k);
return 0;
}
int query_path(int a, int b,int k) {
int ans = 0; int x, y;
int v = upper_bound(W + 1, W + cntW + 1, k) - W - 1;
if (!v)return 0;
while (top[a] != top[b]) {
if (dep[top[a]] < dep[top[b]])swap(a, b);
x = id[top[a]]; y = id[a];
ans += query(root[x-1], root[y], 1, cntW, v);
a = fa[top[a]];
}
if (a == b)return ans;
if (dep[a] > dep[b])swap(a, b);
x = id[a]; y = id[b];
ans += query(root[x-1], root[y], 1,cntW, v);
return ans;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i < n; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
W[i] = z;
addEdge(x, y, z); addEdge(y, x, z);
}
W[n] = 0x3f3f3f3f;
sort(W + 1, W + n + 1);
cntW = unique(W + 1, W + n + 1) - W - 1;
root[0] = build(1, cntW);
dfs1(1, 0);
dfs2(1, 1, 0x3f3f3f3f);
for (int i = 1; i <= n; i++) {
root[i] = insert(root[i - 1], 1, cntW, getid(val[i]));
}
while (m--) {
int a, b, k;
scanf("%d%d%d", &a, &b, &k);
printf("%d
", query_path(a, b, k));
}
}
换了一个写法,就 A 了???
int query_path(int a, int b, int k) {
int lca = LCA(a, b);
int v = upper_bound(W + 1, W + 1 + cntW, k) - W - 1;
if (!v)return 0;
int ans = query(root[0], root[a], 1, cntW, 1, v) + query(root[0], root[b], 1, cntW, 1, v) - 2 * query(root[0], root[lca], 1, cntW, 1, v);
//if (val[lca] <= k)ans--;
return ans;
}
/*
* @Author: zhl
* @Date: 2020-11-10 20:36:59
*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
#define mid ((l+r)>>1)
using namespace std;
const int N = 5e5 + 10;
int n, m;
struct Edge {
int to, next, w;
}E[N << 1];
int head[N], tot;
void addEdge(int from, int to, int w) {
E[++tot] = Edge{ to,head[from],w };
head[from] = tot;
}
int fa[N], sz[N], Tfa[N], dep[N], son[N];
//dfs1处理dep,sz,fa,son(重儿子)
void dfs1(int u, int p) {
fa[u] = p;
dep[u] = dep[p] + 1;
sz[u] = 1;
int mx = -1;
repE(i, u) {
int v = E[i].to;
if (v == p)continue;
dfs1(v, u);
sz[u] += sz[v];
if (sz[v] > mx)mx = sz[v], son[u] = v;
}
}
int cnt;
int id[N], val[N], top[N];
//dfs2 剖分树链
int W[N];//边权
int root[N];
int cntW;
int getid(int x) {
return lower_bound(W + 1, W + cntW + 1, x) - W;
}
int L[N << 5], R[N << 5], sum[N << 5];
int Tot;
int build(int l, int r) {
int u = ++Tot;
if (l < r) {
L[u] = build(l, mid);
R[u] = build(mid + 1, r);
}
return u;
}
int insert(int pre, int l, int r, int pos) {
int u = ++Tot;
L[u] = L[pre];
R[u] = R[pre];
sum[u] = sum[pre] + 1;
if (l >= r)return u;
if (pos <= mid) {
L[u] = insert(L[pre], l, mid, pos);
}
else {
R[u] = insert(R[pre], mid + 1, r, pos);
}
return u;
}
int query(int rt_x, int rt_y, int l, int r, int Lq, int Rq) {
if (Lq <= l and r <= Rq) {
return sum[rt_y] - sum[rt_x];
}
int num = sum[L[rt_y]] - sum[L[rt_x]];//区间内,左半区间的数的数量
int res = 0;
if (Lq <= mid) res += query(L[rt_x], L[rt_y], l, mid, Lq, Rq);
if (Rq > mid) res += query(R[rt_x], R[rt_y], mid + 1, r, Lq, Rq);
return res;
}
int LCA(int a, int b) {
while (top[a] != top[b]) {
if (dep[top[a]] < dep[top[b]])swap(a, b);
a = fa[top[a]];
}
if (dep[a] > dep[b])swap(a, b);
return a;
}
int query_path(int a, int b, int k) {
int lca = LCA(a, b);
int v = upper_bound(W + 1, W + 1 + cntW, k) - W - 1;
if (!v)return 0;
int ans = query(root[0], root[a], 1, cntW, 1, v) + query(root[0], root[b], 1, cntW, 1, v) - 2 * query(root[0], root[lca], 1, cntW, 1, v);
//if (val[lca] <= k)ans--;
return ans;
}
void dfs2(int u, int topf, int w) {
id[u] = ++cnt;
val[cnt] = w;
top[u] = topf;
root[u] = insert(root[fa[u]], 1, cntW, getid(w));
if (!son[u])return;
int x = 0;
repE(i, u)if (E[i].to == son[u]) x = E[i].w;
dfs2(son[u], topf, x);
repE(i, u) {
int v = E[i].to;
if (v == fa[u] or v == son[u])continue;
dfs2(v, v, E[i].w);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i < n; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
W[i] = z;
addEdge(x, y, z); addEdge(y, x, z);
}
W[n] = 0x3f3f3f3f;
sort(W + 1, W + n + 1);
cntW = unique(W + 1, W + n + 1) - W - 1;
root[0] = build(1, cntW);
dfs1(1, 0);
dfs2(1, 1, 0x3f3f3f3f);
while (m--) {
int a, b, k;
scanf("%d%d%d", &a, &b, &k);
printf("%d
", query_path(a, b, k));
}
}
/*
5 400
1 2 7
1 3 4
2 4 5
3 5 2
2 3 1000000000
4 5 1000000000
*/