北京林业大学“计蒜客”杯程序设计竞赛
zz选手只做了7个题
$A、B、C、D、E、G、H$
A.喝酒
题意:
$N瓶酒,3个盖子或者4个空瓶可以换1瓶酒,问能喝几瓶$
分析:
$直接模拟一下,别忘记换的酒也有盖子和瓶子$
代码:
//
// Created by TaoSama on 2016-04-24
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n;
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d", &n);
int ans = n, a = n, b = n;
while(a >= 3 || b >= 4) {
int delta = a / 3 + b / 4;
a = a % 3 + delta;
b = b % 4 + delta;
ans += delta;
}
printf("%d\n", ans);
}
return 0;
}
B.大钉骑马走江湖
题意:
$N*M的图,马走日,问到终点要几步$
分析:
$打个方向表和蹩马腿的表,然后直接bfs就好$
代码:
//
// Created by TaoSama on 2016-04-24
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m;
char s[105][105];
int f[105][105];
int sx, sy, tx, ty;
int d[][2] = {{1, 2}, {1, -2}, { -1, 2}, { -1, -2}, {2, 1}, {2, -1}, { -2, 1}, { -2, -1}};
int no[][2] = {0, 1, 0, -1, 0, 1, 0, -1, 1, 0, 1, 0, -1, 0, -1, 0};
int bfs() {
queue<int> q; q.push(sx * m + sy);
memset(f, -1, sizeof f);
f[sx][sy] = 0;
while(q.size()) {
int u = q.front(); q.pop();
int x = u / m, y = u % m;
for(int i = 0; i < 8; ++i) {
int nx = x + d[i][0], ny = y + d[i][1];
int kx = x + no[i][0], ky = y + no[i][1];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if(kx < 0 || kx >= n || ky < 0 || ky >= m) continue;
if(s[nx][ny] == '#' || s[kx][ky] == '#') continue;
if(f[nx][ny] == -1) {
f[nx][ny] = f[x][y] + 1;
q.push(nx * m + ny);
}
}
}
return f[tx][ty];
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d%d", &n, &m) == 2) {
for(int i = 0; i < n; ++i) {
scanf("%s", s[i]);
for(int j = 0; j < m; ++j) {
if(s[i][j] == 's') sx = i, sy = j;
if(s[i][j] == 'e') tx = i, ty = j;
}
}
printf("%d\n", bfs());
}
return 0;
}
C. Candy
题意:
$N\le10^5个人,每个人有个权,现开始发糖,至少1个$
$要求权比旁边2个人大的,必须糖比他多$
$问最少需要发多少糖$
分析:
$暴力,先给每个人发一个,然后正着补一遍,倒着补一遍就好了$
代码:
//
// Created by TaoSama on 2016-04-24
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, a[N];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d", &n) == 1) {
vector<int> v(n + 1, 1);
for(int i = 1; i <= n; ++i) scanf("%d", a + i);
for(int i = 1; i <= n; ++i) {
if(i > 1 && a[i] > a[i - 1]) v[i] = max(v[i], v[i - 1] + 1);
if(i < n && a[i] > a[i + 1]) v[i] = max(v[i], v[i + 1] + 1);
}
for(int i = n; i; --i) {
if(i > 1 && a[i] > a[i - 1]) v[i] = max(v[i], v[i - 1] + 1);
if(i < n && a[i] > a[i + 1]) v[i] = max(v[i], v[i + 1] + 1);
}
// for(int x : v) printf("%d ", x); puts("");
int ans = accumulate(v.begin() + 1, v.end(), 0);
printf("%d\n", ans);
}
return 0;
}
D. A letter from Chensg
题意:
$求N个串的字典序最小的最长公共子串$
$我很喜欢这封love letter啊$
分析:
$数据非常小,直接从长到短的暴力就好了,正解当然是sa啦$
代码:
//
// Created by TaoSama on 2015-10-30
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n;
string s[15];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; cin >> t;
while(t--) {
cin >> n;
for(int i = 1; i <= n; ++i) cin >> s[i];
string ans;
for(int sz = 60; sz >= 3; --sz) {
for(int st = 0; st + sz - 1 < 60; ++st) {
bool ok = true;
string cur = s[1].substr(st, sz);
for(int i = 2; i <= n; ++i) {
if(s[i].find(cur) == string::npos) {
ok = false;
break;
}
}
if(!ok) continue;
if(!ans.size() || cur < ans) ans = cur;
}
if(ans.size()) break;
}
if(ans.size()) cout << ans << '\n';
else cout << "No significant commonalities\n";
}
return 0;
}
E. delightful world
题意:
$猜1个01串,先现给出N\le 35次猜想,以及对应的猜对的个数\le 5$
$问符合要求的串有几个$
分析:
$meet in middle辣,二进制枚举前半部分,然后哈希这个串的匹配情况成数字,因为猜对个数小嘛$
$然后从另一半计数就好了$
代码:
//
// Created by TaoSama on 2016-04-24
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
typedef long long LL;
int n, m;
char s[15][40];
int a[15];
LL ten[20];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
ten[0] = 1;
for(int i = 1; i < 20; ++i) ten[i] = ten[i - 1] * 10;
while(scanf("%d%d", &n, &m) == 2) {
for(int i = 0; i < m; ++i) scanf("%s%d", s[i], a + i);
map<LL, int> mp;
int half = n >> 1, lft = n - half;
for(int i = 0; i < 1 << half; ++i) {
bool ok = true;
LL sum = 0;
for(int j = 0; j < m; ++j) {
int cnt = 0;
for(int k = 0; k < half; ++k)
if(s[j][k] - '0' == (i >> k & 1)) ++cnt;
if(cnt <= a[j]) sum += cnt * ten[j];
else {
ok = false;
break;
}
}
if(ok) ++mp[sum];
}
LL ans = 0;
for(int i = 0; i < 1 << lft; ++i) {
bool ok = true;
LL sum = 0;
for(int j = 0; j < m; ++j) {
int cnt = 0;
for(int k = 0; k < lft; ++k)
if(s[j][half + k] - '0' == (i >> k & 1)) ++cnt;
if(cnt <= a[j]) sum += (a[j] - cnt) * ten[j];
else {
ok = false;
break;
}
}
if(ok) ans += mp[sum];
}
printf("%lld\n", ans);
}
return 0;
}
G. 易彰彪的一张表
题意:
$N个长度为M的字符串,如果他们首尾相连,问T串是否是合并串的子串$
分析:
$数据很小,直接合并到一起string::find$
代码:
//
// Created by TaoSama on 2016-04-24
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m;
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> n >> m) {
string s, t;
for(int i = 1; i <= n; ++i) {
cin >> t;
s += t;
}
for(int i = 0; i < s.size(); ++i) s[i] = tolower(s[i]);
cin >> t;
for(int i = 0; i < t.size(); ++i) t[i] = tolower(t[i]);
if(s.find(t) != string::npos) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
H. Ivan 的等待焦虑症发作了
题意:
$10个电梯上下楼,会在一些层停留,问到达规定层的时间(不算这层的停留时间)$
分析:
$数据很小直接一层一层走的模拟就好了,一开始写lower_bound没看数据写了半天。$
代码:
//
// Created by TaoSama on 2016-04-24
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, p, wh[5];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d%d", &n, &p) == 2) {
for(int i = 1; i <= n; ++i) scanf("%d", wh + i);
bool s[5][50] = {};
for(int i = 1; i <= n; ++i) {
int cnt; scanf("%d", &cnt);
while(cnt--) {
int x; scanf("%d", &x);
s[i][x] = 1;
}
}
vector<int> ans(n + 1);
for(int i = 1; i <= n; ++i) {
if(wh[i] == p) ans[i] = 0;
else if(wh[i] > p) {
ans[i] = 5;
for(int j = wh[i] - 1; j > p; --j) {
ans[i] += 5;
if(s[i][j]) ans[i] += 15;
}
} else {
ans[i] = 5;
for(int j = wh[i] + 1; j < p; ++j) {
ans[i] += 5;
if(s[i][j]) ans[i] += 15;
}
}
}
for(int i = 1; i <= n; ++i)
printf("%d%c", ans[i], " \n"[i == n]);
}
return 0;
}