湖南2020多校对抗赛round3 CERC2014
湖南2020多校对抗赛round3 CERC2014
题号 | 赛中 | 赛后 |
---|---|---|
Parades | ||
Mountainous landscape | ||
Sums | √ | |
Wheels | √ | |
Can't stop playing | ||
Vocabulary | √ | |
Virus synthesis | ||
Good morning! | √ | |
Bricks | √ | |
Pork barrel | ||
The Imp | ||
Outer space invaders | √ |
这场真是模拟贪心完后就一直dp
人给dp傻了
人给wa傻了
cwolf9牛逼
A.Parades
比较牛逼的树形dp吧,待补
题意:给你一个树,有q个询问,每个询问会占用\(u_i->v_i\)的路径,求最多可以取多少个询问,使得这些询问之间的路径不重合
C.Sums
题意:求一个数是否 是一段连续数字的和,使得最大的那个数字尽可能小
简单推一下就行
\(假设有x项连续的数组成n\)
\(则(a+1)+(a+2)+...+(a+x)=n\)
\(根据等差数列公式可得\)
\(\frac {(a+1+a+x)*x}{2}=n\)
\(a*x+\frac{(1+x)*x}{2}=n\)
\(n-\frac{(1+x)*x}{2}=a*x\)
所以得出这个同余关系就可以直接扫一遍即可
代码如下
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
LL sum[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
for(LL i = 1; i <= 1e5; i++) {
sum[i] = i * (i - 1) / 2LL;
}
for(int i=1;i<=10;i++){
debug1(sum[i]);
}
int T;
scanf("%d", &T);
while(T--) {
LL n;
scanf("%lld", &n);
int flag = 0;
for(LL i = 2; i < 1e5&&!flag; i++) {
debug2(n,sum[i]);
if(sum[i] < n && (n - sum[i]) % i == 0) {
printf("%lld = ", n);
int pos = (n - sum[i]) / i;
debug1(pos);
for(LL j = 0; j < i; j++) {
if(j) {
printf(" + ");
}
printf("%lld", pos + j);
}
printf("\n");
flag = 1;
}
}
if(!flag) {
printf("IMPOSSIBLE\n");
}
}
return 0;
}
D.Wheels
题意:给你n个轮子,第一个轮子是顺时针按照角速度为1 来旋转的,问,n个轮子的旋转状态
模拟一下即可,判断轮子是否相切,角速度之比等于轮子半径的反比
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
struct Point {
int x, y;
LL r;
pair<LL, LL> ans;
int flag;
} a[maxn];
int vis[maxn];
LL get(Point a, Point b) {
return 1LL * (a.x - b.x) * (a.x - b.x) + 1LL * (a.y - b.y) * (a.y - b.y);
}
bool check(Point a, Point b) {
LL disab = get(a, b);
LL disrr = 1LL * (a.r + b.r) * (a.r + b.r);
return disab == disrr;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
vis[i] = 0;
a[i].flag = -1;
a[i].ans = make_pair(1, 1);
scanf("%d%d%lld", &a[i].x, &a[i].y, &a[i].r);
}
a[1].ans = make_pair(1, 1);
a[1].flag = 1;
queue<int> q;
while(!q.empty()) {
q.pop();
}
q.push(1);
while(!q.empty()) {
int now = q.front();
q.pop();
if(vis[now]) continue;
vis[now] = 1;
for(int i = 1; i <= n; i++) {
if(vis[i]) continue;
if(check(a[i], a[now])) {
a[i].flag = !a[now].flag;
a[i].ans = make_pair(a[now].ans.first * a[now].r, a[now].ans.second * a[i].r);
int d = gcd(a[i].ans.first, a[i].ans.second);
a[i].ans.first /= d;
a[i].ans.second /= d;
q.push(i);
}
}
}
for(int i = 1; i <= n; i++) {
if(!vis[i]) {
printf("not moving\n");
} else {
if(a[i].ans.first == 1 && a[i].ans.second == 1) {
printf("1 ");
} else {
if(a[i].ans.second == 1) {
printf("%lld ", a[i].ans.first);
} else {
printf("%lld/%lld ", a[i].ans.first, a[i].ans.second);
}
}
if(a[i].flag) {
printf("clockwise\n");
} else {
printf("counterclockwise\n");
}
}
}
}
return 0;
}
F.Vocabulary
cwolf9绝杀出来的,待补
H.Good morning!
题意:模拟键盘输入,只能从当前按键往左下按,每个按键可以按任意多次,求可以按出来的离给出的数字最近的数是哪个
因为n特别小,所以枚举差值更新答案是否可达即可
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
bool check(int val) {
vector<int>vec;
while(val) {
vec.push_back(val % 10);
val /= 10;
}
reverse(vec.begin(), vec.end());
int pos = vec[0];
bool flag = true;
int sz = vec.size();
for(int i = 1; i < sz && flag; i++) {
if(vec[i] == pos) {
continue;
}
if(vec[i] != 0) {
if(vec[i] < pos) {
flag = 0;
} else {
if(pos == 1 || pos == 4 || pos == 7) {
pos = vec[i];
} else {
if(pos == 2) {
if(vec[i] == 4 || vec[i] == 7) {
flag = 0;
}
}
if(pos == 5) {
if(vec[i] == 7) {
flag = 0;
}
}
if(pos == 3) {
if(vec[i] == 3 || vec[i] == 6 || vec[i] == 9) {
pos = vec[i];
} else {
flag = 0;
}
}
if(pos == 6) {
if(vec[i] == 6 || vec[i] == 9) {
pos = vec[i];
} else {
flag = 0;
}
}
if(pos == 9) {
if(vec[i] == 9) {
pos = vec[i];
} else {
flag = 0;
}
}
if(pos == 0) {
if(vec[i] != 0) {
flag = 0;
}
}
pos = vec[i];
}
}
} else {
if(pos == 1 || pos == 4 || pos == 7 || pos == 2 || pos == 5 || pos == 8 || pos == 0) {
pos = vec[i];
} else {
flag = 0;
}
}
}
return flag;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
int k;
scanf("%d", &k);
for(int i = 0; i <= 1000; i++) {
int Max = k + i;
int Min = max(0, k - i);
if(check(Max)) {
printf("%d\n", Max);
break;
}
if(check(Min)) {
printf("%d\n", Min);
break;
}
}
}
return 0;
}
I.Bricks
题意:给你一些联系的B和W,问你最多可以分割多少块,使得每一块当中B和W的比例是相同的
题解:比例是固定的,b的总数比上w的总数,这个比较好推,假设第一块中b的数量为a1,w的数量为b1
第二块中b的数量为a2,w的数量为b2
那么a1:b1=a2:b2,那么a1+a2:b1+b2=a1:b1
知道了比例后,就从前往后尽可能的使得数量尽可能少的比过去
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
int num[maxn];
int flag[maxn];
char str[5];
LL d[3];
LL sum[3];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
sum[0] = sum[1] = 0;
d[0] = d[1] = 0;
for(int i = 1; i <= n; i++) {
scanf("%d%s", &num[i], str);
if(str[0] == 'B') {
sum[0] += num[i];
flag[i] = 0;
} else {
sum[1] += num[i];
flag[i] = 1;
}
}
if(sum[0] == 0 || sum[1] == 0) {
printf("%d\n", sum[0] + sum[1]);
continue;
}
int ans = 0;
for(int i = 1; i <= n; i++) {
LL x = sum[flag[i]] * d[flag[i] ^ 1] - d[flag[i]] * sum[flag[i] ^ 1];
if(x % sum[flag[i] ^ 1] || x <= 0 || x / sum[flag[i] ^ 1] > num[i]) {
d[flag[i]] += num[i];
} else {
ans++;
d[flag[i]] = num[i] - x / sum[flag[i] ^ 1];
d[flag[i] ^ 1] = 0;
}
}
printf("%d\n", ans);
}
return 0;
}
L.Outer space invaders
题意,有n个外星人,外星人存在的时间是L[i],R[i],你要在外星人存在的时间内消灭外星人,外星人距离你为d[i],消灭距离为d[i]的外星人所需要花费的最小代价为d[i]
问消灭所有外星人所花费的最小代价
题解
将外星人存在的时间离散化后dp
\(dp_{ij}表示消灭时间在i-j之间的所有外星人所需要花费的最小代价为多少,那么一定是该时间段内d[i]的最大值,然后枚举时间点转移即可\)
\(dp_{ij}=min(dp[i][k-1]+dp[k+1][j]+d[k])\)
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
int a[maxn];
int b[maxn];
int d[maxn];
vector<int> vec;
int dp[605][605];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
vec.clear();
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d%d%d", &a[i], &b[i], &d[i]);
vec.push_back(a[i]);
vec.push_back(b[i]);
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
int sz = vec.size();
for(int i = 1; i <= n; i++) {
a[i] = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin();
b[i] = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin();
}
for(int cnt = 0; cnt < sz; cnt++) {
for(int i = 0; i + cnt < sz; i++) {
int pos = 0;
int j = i + cnt;
for(int k = 1; k <= n; k++) {
if(a[k] >= i && b[k] <= j) {
if(pos == -1 || d[pos] < d[k]) {
pos = k;
}
}
}
if(pos == 0) {
dp[i][j] = 0;
} else {
dp[i][j] = INF;
for(int k = a[pos]; k <= b[pos]; k++) {
dp[i][j] = min(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + d[pos]);
}
}
}
}
printf("%d\n", dp[0][sz - 1]);
}
return 0;
}