uestc summer training #2
Posted aragaki
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uestc summer training #2相关的知识,希望对你有一定的参考价值。
A
B
签到题
D
模拟题
F
给你一个中序遍历 和每个点的权值 问你存不存在一颗树使得每个节点的祖先和它的权值是互质的
解:
质因数分解+分治模拟
因为中序遍历有个特点 如果一个点是一个子树的根的话 左儿子都在左边 右儿子都在右边
所以要求互质的是一段区间 用GCD来做的话肯定会超时 我们给每个合数一个leftprime表示该合数质因数分解后最小的质数
首先我们从左到右枚举 维护每个质数所到的最右边 更新每个合数的答案 再反过来从右到左做一次
然后模拟树分治找到根递归地看能不能构造树
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; const double eps = 1e-8; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9; const int MAXN = 1e6 + 5, MAXM = 1e5 + 5; const int MAXQ = 100010; //int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1; /*inline void addedge(int u, int v, ll c) { to[++tot] = v; nxt[tot] = Head[u]; cost[tot] = c; Head[u] = tot; }*/ inline void read(int &v) { v = 0; char c = 0; int p = 1; while (c < ‘0‘ || c > ‘9‘) { if (c == ‘-‘) { p = -1; } c = getchar(); } while (c >= ‘0‘ && c <= ‘9‘) { v = (v << 3) + (v << 1) + c - ‘0‘; c = getchar(); } v *= p; } const int N = 10000000 + 5; int MAXX = -1; bool flagsum; int ptot = 0; int num[N]; int father[N]; int prime[N]; bool check[N]; int fanwei[N]; int leftprime[N]; int lans[N], rans[N]; void Euler() { ll now; for (int i = 2; i <= MAXX; i ++) { if (!check[i]) { prime[ptot ++] = i; } for (int j = 0; j < ptot; j ++) { now = 1LL * prime[j] * i; if (now > MAXX) { break; } check[now] = 1; leftprime[now] = prime[j]; if (i % prime[j] == 0) { break; } } } } bool get_ans(int fa, int l, int r) { int flag = 0; if (l > r) { return true; } int aim; int len = (r - l - 1) / 2 + ((r - l - 1) & 1); for (int i = 0; i <= len; i++) { aim = l + i; if (lans[aim] < l && rans[aim] > r) { //cout << fa << " " << l << " " << r << " " << i << endl; //cout << lans[i] << " " << rans[i] << endl; flag = 1; flag = flag && get_ans(aim, l, aim - 1) && get_ans(aim, aim + 1, r); if (flag) { father[aim] = fa; return true; } else { return false; } } aim = r - i; if (lans[aim] < l && rans[aim] > r) { //cout << fa << " " << l << " " << r << " " << i << endl; //cout << lans[i] << " " << rans[i] << endl; flag = 1; flag = flag && get_ans(aim, l, aim - 1) && get_ans(aim, aim + 1, r); if (flag) { father[aim] = fa; return true; } else { return false; } } } return false; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; int cnt; read(n); for (int i = 1; i <= n; i++) { read(num[i]); MAXX = max(MAXX, num[i]); } Euler(); // for (int i = 1; i <= 20; i++) // { // cout << i << " " << leftprime[i] << endl; // } for (int i = 1; i <= n; i++) { rans[i] = n + 1; } for (int i = 1; i <= n; i++) { cnt = num[i]; if (cnt == 1) { continue; } //cout<<i<<" "; if (check[cnt] == 0) { //cout << "l "<<cnt << endl; lans[i] = max(fanwei[cnt], lans[i]); fanwei[cnt] = i; continue; } while (check[cnt]) { //cout << "l " << cnt << endl; int primenow = leftprime[cnt]; lans[i] = max(fanwei[primenow], lans[i]); fanwei[primenow] = i; while (cnt % primenow == 0) { cnt /= primenow; } } if (cnt == 1) { continue; } else { //cout << "l " << cnt << endl; lans[i] = max(fanwei[cnt], lans[i]); fanwei[cnt] = i; } } for (int i = 1; i <= N; i++) { fanwei[i] = n + 1; } for (int i = n; i >= 1; i--) { cnt = num[i]; if (cnt == 1) { continue; } //cout<<i<<" "; if (check[cnt] == 0) { //cout << "r "<<cnt << endl; rans[i] = min(fanwei[cnt], rans[i]); fanwei[cnt] = i; continue; } while (check[cnt]) { //cout << "r "<<cnt << endl; int primenow = leftprime[cnt]; rans[i] = min(fanwei[primenow], rans[i]); fanwei[primenow] = i; while (cnt % primenow == 0) { cnt /= primenow; } } if (cnt == 1) { continue; } else { // cout << "r "<<cnt << endl; // cout << cnt << endl; rans[i] = min(fanwei[cnt], rans[i]); fanwei[cnt] = i; } } // for(int i=1;i<=n;i++) // { // cout<<i<<" "<<lans[i]<<" "<<rans[i]<<endl; // } flagsum = get_ans(0, 1, n); if (!flagsum) { cout << "impossible" << endl; } else { for (int i = 1; i <= n; i++) { cout << father[i]; if (i != n) { cout << " "; } } cout << endl; } return 0; }
G
几何题
H
小的直接暴力 大的加给大的
I
背包DP 记录路径还需要一个二维数组
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; const double eps = 1e-8; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9; const int MAXN = 1e6 + 5, MAXM = 1e5 + 5; const int MAXQ = 100010; //int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1; /*inline void addedge(int u, int v, ll c) { to[++tot] = v; nxt[tot] = Head[u]; cost[tot] = c; Head[u] = tot; }*/ inline void read(int &v) { v = 0; char c = 0; int p = 1; while (c < ‘0‘ || c > ‘9‘) { if (c == ‘-‘) { p = -1; } c = getchar(); } while (c >= ‘0‘ && c <= ‘9‘) { v = (v << 3) + (v << 1) + c - ‘0‘; c = getchar(); } v *= p; } struct node { int index; int w; int t; } app[505]; bool cmp(node a, node b) { return a.t > b.t; } int dp[505][10005]; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n, m; int d, s; scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d %d", &d, &s); app[i].index = i; app[i].w = max(d, s); app[i].t = app[i].w - s; } sort(app + 1, app + 1 + n, cmp); for (int i = 0; i <= n; i++) { for (int j = 0; j <= m; j++) { dp[i][j] = -INT_MAX; } } dp[0][m] = 0; for (int i = 1; i <= n; i++) { for (int j = 0; j <= m; j++) { dp[i][j] = dp[i - 1][j]; } for (int j = 0; j <= m; j++) { if (dp[i - 1][j] >= 0) { if (j < app[i].w) { continue; } dp[i][j - app[i].w + app[i].t] = max(dp[i - 1][j] + 1, dp[i][j - app[i].w + app[i].t]); } } } int anser = 0; for (int i = 0; i <= m; i++) { anser = max(anser, dp[n][i]); } cout << anser << endl; return 0; }
J
找规律题
我们可以通过打暴力程序对比发现每个2一轮一轮地模拟和一个一个地模拟得到的结果是一样的
但是直接把一个一个滚的模拟交上去会T7 需要再简化一下
每当遇到一个二 找到它左边最近的0和右边最近的0位置分别为L与R
则这一段数列除了L+R-i这个位置变成0 其他位置都会变成1
K
概率题
以上是关于uestc summer training #2的主要内容,如果未能解决你的问题,请参考以下文章
2017ecjtu-summer training #4 UESTC 30
UESTC 2016 Summer Training #1 J - Objects Panel (A) 按条件遍历树
2017 UESTC Training for Dynamic Programming