这是第二次也是最后一次去参加怀化学院的校赛,一样的行程一样的住宿,C&V学长的安排就是轻松。大佬说写题解会收获多多,只会写简单题的我就来划划水了。
先放传送门,密码:hhtc20190607
温暖的签到题:范围不大,模拟即可,直接上代码。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 20007;
int k, a[MAXN];
int main() {
int num = 0, cnt = 1;
for(int i = 1; i < MAXN;) {
for(int j = cnt; j > 0 && i < MAXN; j--) {
num += cnt;
a[i++] = num;
}
cnt++;
}
while(scanf("%d", &k) != EOF)
printf("%d\n", a[k]);
return 0;
}
求解n的二进制有多少个1,bitset直接解决。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 20007;
int n;
int main() {
while(scanf("%d", &n) != EOF) {
bitset<1000> bi(n);
printf("%d\n", bi.count());
}
return 0;
}
打表得到结论,输出Yes当且仅当n是2的次幂,至于证明就不放了(不会啊)。
场上用的for判2的次幂,场下经学长提点可以判n的2进制中1的个数,于是又用了bitset。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 20007;
int n;
int main() {
while(scanf("%d", &n) != EOF) {
bitset<1000> bi(n);
if(bi.count() == 1) puts("Yes");
else puts("No");
}
return 0;
}
当L==R时,最小的因子就是L的最小因子(场上因这个点还wa了TAT)。
当L < R时,最小的因子是2,显然的结论。
下面的代码用的for循环求最小因子,显然可以优化,不过对于这题的范围来说已经足够了。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 20007;
int l, r;
int main() {
while(scanf("%d%d", &l, &r) != EOF) {
if(l != r) puts("2");
else {
for(LL i = 2;; i++) {
if(i * i > l) {
printf("%d\n", l);
break;
}
if(l % i == 0) {
printf("%lld\n", i);
break;
}
}
}
}
return 0;
}
经典贪心问题:汽车加油的原题
场上信心满满的写,然后wa到怀疑人生,场下找了一天的bug才发现i++的位置放错了,造的数据也都过了,一失足成千古恨。
附上暖心的测试数据:
4 10
10 1
5 1
5 2
5 3
3 15
10 2
9 1
8 3
2 10
5 10
5 1
3 10
1 1
1 1
9 2
4 10
1 1
1 2
9 2
1 3
4 10
1 1
1 2
9 3
1 4
3 2
1 5
1 4
1 3
3 14
5 2
5 10
5 1
30
41
55
11
14
15
12
25
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 100077;
int n, t;
LL d[MAXN], p[MAXN];
int main() {
while(cin >> n >> t) {
bool pr = true;
for(int i = 0; i < n; i++) {
cin >> d[i] >> p[i];
if(d[i] > t) pr = false;
}
if(!pr) cout << -1 << endl;
else {
d[n] = p[n] = INF;
LL ans = 0;
LL neng = 0;
int now = 0;
while(now < n) {
int r = now + 1;
int idex = now + 1;
LL num = t - d[now];
while(num > d[r]) {
num -= d[r];
r++;
if(p[r] < p[idex]) idex = r;
}
if(p[now] <= p[idex]) {
if(r == n) {
LL sum = -neng;
for(int i = now; i < n; i++) sum += d[i];
ans += sum * p[now];
break;
} else {
ans += (t - neng) * p[now];
neng = t;
for(int i = now; i < idex; i++) neng -= d[i];
now = idex;
}
} else {
LL sum = -neng;
int i;
for(i = now; i < r && p[i] >= p[now]; i++) sum += d[i];
ans += sum * p[now];
neng = 0;
now = i;
}
}
cout << ans << endl;
}
}
return 0;
}
简单搜索题,从蛋糕的位置起搜索能到的点,然后再计数即可,注意蛋糕可能不止一个(场上数据出锅再次wa到怀疑人生)。
注:下面的代码是dfs递归过的,实际上考虑极限情况递归层数可以到1e6,爆栈警告,过了只能说数据不够强。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 1007;
int n, m;
char s[MAXN][MAXN];
char t[7] = {"swad"};
int dx[4] = { -1, 1, 0, 0};
int dy[4] = {0, 0, 1, -1};
bool check(int id, int x, int y) {
if(x < 0 || x >= n) return false;
if(y < 0 || y >= m) return false;
if(s[x][y] != t[id]) return false;
return true;
}
void dfs(int x, int y) {
for(int i = 0; i < 4; i++) {
int nex = x + dx[i];
int ney = y + dy[i];
if(check(i, nex, ney)) {
s[nex][ney] = '*';
dfs(nex, ney);
}
}
}
int main() {
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 0; i < n; i++) scanf("%s", s[i]);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(s[i][j] == 'o') dfs(i, j);
int cnt = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(s[i][j] == '*' || s[i][j] == 'o') cnt++;
printf("%d\n", cnt);
}
return 0;
}
简单模拟题居然爆零了,哭晕
开数组记录每台服务器当前的右边界,对于每个任务枚举判断并更新右边界即可。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 107;
int n, q;
int R[MAXN];
int check(int t) {
int ret = 0;
for(int i = 1; i <= n; i++)
if(R[i] < t) ret++;
return ret;
}
int jisuan(int t, int k, int d) {
int num = t + d - 1;
int ret = 0;
for(int i = 1; k > 0; i++)
if(R[i] < t) R[i] = num, k--, ret += i;
return ret;
}
int main() {
while(scanf("%d%d", &n, &q) != EOF) {
memset(R, 0, sizeof(R));
while(q--) {
int t, k, d;
scanf("%d%d%d", &t, &k, &d);
if(check(t) >= k) printf("%d\n", jisuan(t, k, d));
else puts("-1");
}
}
return 0;
}
又是一道搜索题,先搜索出包含目标地点的地雷区,再计算出因两地雷相邻而减少的边数
周长=地雷数*4-减少边数
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 37;
int n, m, x, y;
char s[MAXN][MAXN];
int dx[8] = { -1, 1, 0, 0, -1, -1, 1, 1};
int dy[8] = {0, 0, 1, -1, 1, -1, 1, -1};
void dfs(int x, int y) {
if(x < 0 || x >= n) return;
if(y < 0 || y >= m) return;
if(s[x][y] != 'X') return;
s[x][y] = '*';
for(int i = 0; i < 8; i++)
dfs(x + dx[i], y + dy[i]);
}
int quchong(int x, int y) {
int ret = 0;
for(int i = 0; i < 4; i++) {
int nex = x + dx[i];
int ney = y + dy[i];
if(nex < 0 || nex >= n) continue;
if(ney < 0 || ney >= m) continue;
if(s[nex][ney] != '*') continue;
ret++;
}
return ret;
}
int main() {
while(scanf("%d%d%d%d", &n, &m, &x, &y) != EOF) {
for(int i = 0; i < n; i++) scanf("%s", s[i]);
dfs(x - 1, y - 1);
int cnt = 0, qu = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(s[i][j] == '*') {
cnt++;
qu += quchong(i, j);
}
printf("%d\n", cnt * 4 - qu);
}
return 0;
}
还是搜索题:dfs枚举每种走的方案+剪枝(没剪枝T了TAT)
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 37;
int n, m, k;
bool ans[MAXN];
int a[MAXN][MAXN];
bool f[MAXN][MAXN][MAXN];
void dfs(int num, int x, int y) {
if(x < 0 || x >= n) return;
if(y < 0 || y >= m) return;
num = num * a[x][y] % k;
if(x == n - 1 && y == m - 1) ans[num] = true;
if(f[x][y][num]) return;
f[x][y][num] = true;
dfs(num, x + 1, y);
dfs(num, x, y + 1);
}
int main() {
while(scanf("%d%d%d", &n, &m, &k) != EOF) {
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
memset(f, false, sizeof(f));
memset(ans, false, sizeof(ans));
dfs(1, 0, 0);
int cnt = 0;
for(int i = 0; i < k; i++)
if(ans[i]) cnt++;
printf("%d\n", cnt);
for(int i = 0; i < k; i++)
if(ans[i]) printf("%d ", i);
putchar('\n');
}
return 0;
}
至臻*自闭
理论AC的做法,把迷宫向外拓展一圈,如果能从中间的’S’走到外面的任意一个’S’即可无限远,然而我wa了
字符串处理的题
题意:每加进来一个字符,如果和已有的字符最后一位不一样,则先反转再加上新字符,否则直接加上新字符。
直接模拟是可以过的,然而我们仔细考虑一下,整个串是0还是1只跟最后一个字符有关,所以直接判断最后一个字符然后输出字符串长度计即可。
const int INF = 0x3f3f3f3f; ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf; ///-808 464 433
const int mod = 1000000007;
const double eps = 1e-5;
const int MAXN = 20007;
string s;
int main() {
while(cin >> s) {
int len = s.length();
if(s[len - 1] == '0') cout << len << " " << 0 << endl;
else cout << 0 << " " << len << endl;
}
return 0;
}
怀化之行结束了,第一次体验到没人带榜的感觉,我就是带榜的人,结果把榜带歪了 ,一开始装环境装的我头晕眼花的,但问题不大,看到题后感觉比去年容易了不少,应该没有难题,有AK的理论可能,遇到了很多问题,在场上要寻求速度对于很多的细节反而没把握好,也不应该死磕一两道题,场下才发现有简单题没动。果然大佬说的没错,在场上想要超常发挥相当的难,一般来说反而会比平时练习差一筹。快退役选手 弱鸡要准备期末考试了~
对于18级:本来看完题目后觉得这次应该稳了,花了这么多时间在搜索上,这次血赚,然后结束一看榜。。。不知道怎么形容当时的无语。。。