Day-1
考试前一天晚,没上竞赛课,教练叫我们在家做题,别说不愧是信心赛题目都海星,做完后就睡觉了不过有一道题数据好像错了
Day0
考前
早上6:00就起床了,可能是想跟着大部队吧,没有直接去考场而是去了学校,一行人都上了车,不过初一是在是太吵了(跟我们初一时一样)
上了车跟一旁的yzk一起背了一下模板然后差不多就到了NK。不得不说NK的硬件真的要好亿一些。
考前教练反复跟我们说一定要保存,一定要调整好心态。(不然就是给CCF送钱)
考时
拿到第一道题一眼看穿就是从大到小看小于2的几次方,之后再减,打完过完样例就跑了
T1.马蜂清奇
#include<cstdio>
int Pow(int f) {
int sum = 2, ans = 1;
while(f) {
if(f & 1) {
ans *= sum;
}
sum *= sum;
f >>= 1;
}
return ans;
}
int main() {
// freopen("power.in", "r", stdin);
// freopen("power.out", "w", stdout);
int n, sum = 1, tot = 0, cnt = 0, g;
scanf("%d", &n);
g = n;
while(sum < n) {
sum *= 2;
tot ++;
}
for(int i = tot; i >= 1; i --) {
int s = Pow(i);
if(s <= g) {
g -= s;
}
} if(g != 0) {
printf("%d", -1);
} else {
for(int i = tot; i >= 1; i --) {
int s = Pow(i);
if(s <= n) {
n -= s;
printf("%d ", s);
}
}
}
return 0;
}
T2.
考试的时候没有看数据范围成绩<=600,于是就打了一个n^2的略带优化的代码就草草了事,考后才发现直接桶排(600n)就可以了
考试时的代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct lx {
int l, id;
}a[100005];
int Max(int x, int y) { return x > y ? x : y; }
int Min(int x, int y) { return x < y ? x : y; }
bool cmp(lx x, lx y) {
if(x.l == y.l) {
return x.id < y.id;
} return x.l > y.l;
}
int main() {
// freopen("live.in", "r", stdin);
// freopen("live.out", "w", stdout);
int n, w;
scanf("%d %d", &n, &w);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i].l);
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i ++) {
int tot = i * w / 100, cnt = 0, ans = 0x7f7f7f7f;
tot = Max(tot, 1);
for(int j = 1; j <= n; j ++) {
if(cnt == tot) break;
if(a[j].id <= i) {
cnt ++;
// printf("%d %d %d\n", a[j].l, a[j].id, i);
ans = Min(ans, a[j].l);
}
}
printf("%d ", ans);
}
return 0;
}
正解
#include<cstdio>
#include<algorithm>
using namespace std;
struct lx {
int l, id;
}a[100005];
int s[605];
int Max(int x, int y) { return x > y ? x : y; }
int Min(int x, int y) { return x < y ? x : y; }
bool cmp(lx x, lx y) {
if(x.l == y.l) {
return x.id < y.id;
} return x.l > y.l;
}
int main() {
// freopen("live.in", "r", stdin);
// freopen("live.out", "w", stdout);
int n, w;
scanf("%d %d", &n, &w);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i].l);
s[a[i].l] ++;
// printf("%d %d\n", a[i].l, s[a[i].l]);
int tot = i * w / 100, sum = 0;
tot = Max(tot, 1);
for(int j = 600; j >= 0; j --) {
if(s[j]) {
sum += s[j];
// printf("%d %d %d\n", i, j, s[j]);
if(sum >= tot) {
printf("%d ", j);
break;
}
}
}
}
return 0;
}
T4.
考试的时候可能是太浮躁了,没有认真想就先开始打了代码,打了dfs爆搜,和瞎搞最短路SPFA两种,中间也想到是DP,当时想的时候认为跟数字三角形很像,但总觉得有后效型降智了,于是就没有认真打,其实只要从左向右枚举,每次只考虑(上面,左面,下面)的情况就不会有后效性了,于是就可以在内层循环从上到下,从下到上分别DP,讨论两种情况就可以了方程是:
dp[i][j][0] = Max(dp[i - 1][j][0], Max(dp[i][j - 1][0], dp[i][j - 1][1])) + a[i][j];
和 dp[i][j][1] = Max(dp[i + 1][j][1], Max(dp[i][j - 1][0], dp[i][j - 1][1])) + a[i][j];
#include<cstdio>
#include<cstring>
#define int long long
int dp[1005][1005][5];
int a[1005][1005];
int Max(int x, int y) { return x > y ? x : y; }
signed main() {
int n, m;
scanf("%lld %lld", &n, &m);
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
scanf("%lld", &a[i][j]);
}
} memset(dp, -0x3f, sizeof(dp));
dp[0][1][0] = 0;
for(int i = 1; i <= n; i ++) dp[i][1][0] = a[i][1] + dp[i - 1][1][0];
for(int j = 2; j <= m; j ++) {
for(int i = 1; i <= n; i ++) {
dp[i][j][0] = Max(dp[i - 1][j][0], Max(dp[i][j - 1][0], dp[i][j - 1][1])) + a[i][j];
}
for(int i = n; i >= 1; i --) {
dp[i][j][1] = Max(dp[i + 1][j][1], Max(dp[i][j - 1][0], dp[i][j - 1][1])) + a[i][j];
}
}
printf("%lld", Max(dp[n][m][1], dp[n][m][0]));
}
CSP-J就这样结束了,考得不是很好,但还是学到了很多,明白了考试时一定要看数据范围(面向数据编程)懂得都懂,打代码时一定要慢,想好了在答题,不然我自己就是前车之鉴。