湘潭大学的校赛对ACM新手的考察还是很全面很合理的,题目不难,多掌握些知识就可以都做出来。
题目链接:点这儿。
给你一个开始时间和结束时间,让你算一下这中间经过了多少秒。
这题是个签到题,模拟下减法就行了,注意代码的简洁写法。
#include
using namespace std;
int main()
{
for (int T; EOF != scanf("%d", &T); ) {
for (int d[2], h[2], m[2], s[2]; T--; ) {
for (int i = 0; i < 2; i++)
scanf("%dday%d:%d:%d", &d[i], &h[i], &m[i], &s[i]);
printf("%d\n", (d[1] - d[0]) * 60 * 60 * 24 +
(h[1] - h[0]) * 60 * 60 +
(m[1] - m[0]) * 60 +
s[1] - s[0]);
}
}
return 0;
}
换个角度看这个题,代码量会减少很多。
用str
中的字符在mp
中查找,然后在对应的行列上++
,最后按照按行优先的方式去遍历行列,输出就行。
#include
using namespace std;
const char mp[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int main()
{
int T;
for (scanf("%d", &T); T--; ) {
char str[1 << 9];
scanf("%s", str);
int r[6] = {0}, c[6] = {0};
for (int i = 0; str[i]; ++i) {
int sum = 0;
for (; mp[sum] && mp[sum] != str[i]; ++sum) {}
++r[sum / 6];
++c[sum % 6];
}
int max_r = *max_element(r, r + 6);
int max_c = *max_element(c, c + 6);
for (int i = 0; i < 6; i++)
for (int j = 0; j < 6; j++)
if (r[i] == max_r && c[j] == max_c)
putchar(mp[i * 6 + j]);
puts("");
}
return 0;
}
这题数据方位不大,于是暴力就行,开一个数组,对于爆炸区域中的每一个格子都++
,最后维护一个最大值就行了,注意题中的不考虑边界和角落在代码中的体现。
这题如果数据范围大了还要进行离散化然后二维树状数组维护。这里提一下。
#include
using namespace std;
#define MAX_SIZE 105
int main()
{
int T;
for (scanf("%d", &T); T--; ) {
int n;
scanf("%d", &n);
int mp[MAX_SIZE * MAX_SIZE] = {0};
for (int i = 0, x1, y1, x2, y2; i < n; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
for (int ii = x1 + 1; ii <= x2; ++ii)
for (int jj = y1 + 1; jj <= y2; ++jj)
++mp[ii * MAX_SIZE + jj];
}
printf("%d\n", *max_element(mp, mp + MAX_SIZE * MAX_SIZE));
}
return 0;
}
先凑出最大的那个二进制,然后利用100
可以转化成011
把最大的二进制逐步变成最小的二进制就行了。
#include
using namespace std;
typedef long long LL;
int f[44];
int main()
{
f[0] = 1, f[1] = 2;
for (int i = 2; i < 44; f[i] = f[i - 1] + f[i - 2], ++i) {}
int T, n;
for (scanf("%d", &T); T--; ) {
scanf("%d", &n);
LL ans = 0;
for (unsigned int bit; n; n -= f[bit - 1]) {
bit = lower_bound(f, f + 44, n + 1) - f;
ans |= 1LL << bit - 1;
}
bool f = true;
while (f) {
f = false;
for (int i = 0; 1LL << i <= ans; ++i)
if (i > 1 && 1LL << i & ans && !(1LL << i - 1 & ans) && !(1LL << i - 2 & ans)) {
ans &= ~(1LL << i);
ans |= 1LL << i - 1;
ans |= 1LL << i - 2;
f = true;
break;
}
}
printf("%lld\n", ans);
}
return 0;
}
二分找能吃的最后一种食物,然后预处理美味度的最大值。
#include
using namespace std;
int main()
{
int T;
for (scanf("%d", &T); T--; ) {
int n, m, t;
scanf("%d%d", &n, &m);
vectorint , int> > arr;
for (int i = 0, x, y; i < n; i++)
scanf("%d%d", &x, &y), arr.emplace_back(x, y);
sort(arr.begin(), arr.end());
vector<int> dp(n);
dp[0] = arr[0].second;
for (int i = 1; i < n; dp[i] = max(arr[i].second, dp[i - 1]), ++i) {}
for (; m--; ) {
scanf("%d", &t);
auto it = lower_bound(arr.begin(), arr.end(), make_pair(t + 1, 0)) - arr.begin();
printf("%d\n", it == 0 ? 0 : dp[it - 1]);
}
}
return 0;
}
很明显的广搜,不过要注意下面两点:
multimap
映射出入口关系。#include
using namespace std;
const int INF = 0x3f3f3f3f;
const int dirx[] = {0, 0, 1, -1};
const int diry[] = {1, -1, 0, 0};
int main()
{
for (int n, m, q; EOF != scanf("%d%d%d", &n, &m, &q); ) {
vector<int> dp(n * m, INF);
vector<string> mp(n);
for (int i = 0; i < n; cin >> mp[i++]) {}
multimapint , int>, pair<int, int> > traces;
for (int i = 0, x, y, x2, y2; i < q; i++) {
cin >> x >> y >> x2 >> y2;
if (mp[x][y] == '#' || mp[x2][y2] == '#')
continue;
traces.insert(make_pair(make_pair(x, y), make_pair(x2, y2)));
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (mp[i][j] == 'S') {
priority_queueint, pair<int, int> >,
vectorint , pair<int, int> > >,
greaterint, pair<int, int> > >
> que;
int ans = -1;
dp[i * m + j] = 0;
que.push(make_pair(0, make_pair(i, j)));
while (!que.empty()) {
auto now = que.top();
que.pop();
if (mp[now.second.first][now.second.second] == 'T') {
ans = dp[now.second.first * m + now.second.second];
break;
}
for (int k = 0; k < 4; k++) {
int tx = now.second.first + dirx[k];
int ty = now.second.second + diry[k];
if (tx >= 0 && tx < n && ty >= 0 && ty < m && mp[tx][ty] != '#' &&
now.first + 1 < dp[tx * m + ty])
dp[tx * m + ty] = now.first + 1,
que.push(make_pair(dp[tx * m + ty], make_pair(tx, ty)));
}
auto s2e = traces.equal_range(now.second);
for (auto it = s2e.first; it != s2e.second; ++it) {
if (now.first + 3 < dp[it->second.first * m + it->second.second])
dp[it->second.first * m + it->second.second] = now.first + 3,
que.push(make_pair(now.first + 3, it->second));
}
}
cout << ans << endl;
goto F;
}
}
}
F:;
}
return 0;
}
这题在博客深入浅出矩阵快速幂及其简单应用中是一个例题,看看这篇博客。
#include
using namespace std;
typedef long long LL;
#define MOD 1000000007LL
#define MAX_N 6
template<typename T, int N = 1>
struct Matrix {
Matrix(int f = 0) : n(sizeof(data[0]) / sizeof(data[0][0])) {
memset(data, 0, sizeof(data));
if (f)
for (int i = 0; i < n; data[i][i] = 1, ++i) {}
}
Matrix operator * (const Matrix& other) const {
Matrix ret;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
ret.data[i][j] = (ret.data[i][j] + data[i][k] * other.data[k][j] % MOD) % MOD;
return ret;
}
Matrix operator + (const Matrix& other) const {
Matrix ret;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
ret.data[i][j] = (data[i][j] + other.data[i][j]) % MOD;
return ret;
}
Matrix& operator % (const Matrix& other) {
return *this;
}
T data[N][N];
int n;
};
template<typename T>
T mul(T a, LL n, LL mod)
{
T ret(1);
for (; n; n >>= 1) {
ret = ret * (n & 1 ? a : T(1)) % mod;
a = a * a % mod;
}
return ret;
}
const LL modulu[MAX_N][MAX_N] = {
{1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0},
{0, 0, 1, 3, 3, 1},
{0, 0, 0, 1, 2, 1},
{0, 0, 0, 0, 1, 1},
{0, 0, 0, 0, 0, 1}
};
int main()
{
int T;
cin >> T;
for (LL n; T--; ) {
cin >> n;
if (n <= 1) {
cout << n << endl;
continue;
}
Matrix a;
memcpy(a.data, modulu, sizeof(modulu));
a = mul(a, n - 1, MOD);
cout << (a.data[0][0] * 1 + a.data[0][1] * 0 + a.data[0][2] * 8 +
a.data[0][3] * 4 + a.data[0][4] * 2 + a.data[0][5]) % MOD << endl;
}
return 0;
}
线段树,用二进制来存储哪种颜色存在于桶中。
应该算一个裸的线段树模板题。
#include
using namespace std;
typedef long long LL;
#define MAX_SIZE (100000 * 4 + 100)
pair nodes[MAX_SIZE];
pair<int, int> childs[MAX_SIZE];
int n, m;
void build(int root, int l, int r)
{
nodes[root].first = nodes[root].second = 0;
childs[root].first = l;
childs[root].second = r;
if (l == r)
return ;
build(root << 1, l, (l + r) >> 1);
build(root << 1 | 1, ((l + r) >> 1) + 1, r);
}
void passLazy(int root)
{
nodes[root << 1].first |= nodes[root].first;
nodes[root << 1 | 1].first |= nodes[root].first;
nodes[root << 1].second |= nodes[root].first;
nodes[root << 1 | 1].second |= nodes[root].first;
nodes[root].first = 0;
}
void update(int root, int l, int r, int c)
{
if (l <= childs[root].first && childs[root].second <= r) {
nodes[root].second |= 1LL << c;
nodes[root].first |= 1LL << c;
return ;
}
if (nodes[root].first)
passLazy(root);
if (l <= (childs[root].first + childs[root].second) >> 1)
update(root << 1, l, r, c);
if (r > (childs[root].first + childs[root].second) >> 1)
update(root << 1 | 1, l, r, c);
nodes[root].second |= nodes[root << 1].second | nodes[root << 1 | 1].second;
}
LL query(int root, int l, int r)
{
if (l <= childs[root].first && childs[root].second <= r)
return nodes[root].second;
if (nodes[root].first)
passLazy(root);
LL ret = 0;
if (l <= (childs[root].first + childs[root].second) >> 1)
ret |= query(root << 1, l, r);
if (r > (childs[root].first + childs[root].second) >> 1)
ret |= query(root << 1 | 1, l, r);
return ret;
}
int main()
{
while (EOF != scanf("%d%d", &n, &m)) {
build(1, 1, n);
int num, l, r, c;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &num, &l, &r);
switch (num) {
case 1:
scanf("%d", &c);
update(1, l, r, c);
break;
case 2: {
LL ans = query(1, l, r);
bitset<64> cnt(ans);
printf("%d\n", cnt.count());
break;
}
default:
assert(0);
}
}
}
return 0;
}