G. Fibonacci
签到题,总感觉推了一个非常笨重的公式。。。
当然, 1e9
日常爆int,要用 long long
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
int n, sum = 0;
cin >> n;
sum += (n % 3 * 2 + (n / 3 - 1) * 3) * (n / 3) / 2;
if (n % 3) sum += (1 + (n - n % 3) / 3) * (n - n % 3) / 3;
else sum += (1 + n / 3) * n / 3;
cout << sum;
return 0;
}
M. Gitignore
一道模拟题,利用 map
的有序,将每一段文件地址的前缀目录导入 map
,被保护则 value = 0
,需删除则 value = 1
,同时当删除一个目录后,这个目录的子目录无需再次执行删除,子目录的检测采用字符串切割与字符 /
在目录中出现次数作为判定依据,这种写法的好处是无需考虑不同目录级数下的同名文件。
思考过程中被卡了一段时间,卡的原因就是只用字符串切割判断,而没有判断目录级数,卡住的自造测试数据与输出如下:
1
3 1
aa/bb
aa/bbb
aa/bbbb
aa
程序输出为(带 **
的是调试数据,即 map
的元素顺序输出,在程序中已注释掉):
**aa 0
**aa/bb 1
**aa/bbb 1
**aa/bbbb 1
1
下面是满分代码:
#include <bits/stdc++.h>
#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(x, y, z) for(int (x)=(y);(x)<=(z);++(x))
#define psi pair<string,int>
#define int long long
using namespace std;
int T = 1;
map<string, int> mp;
void solve() {
int n, m;
string a;
mp.clear();
cin >> n >> m;
rep(i, 1, n) {
cin >> a;
cin.sync();
mp.insert((psi) {a, 1});
string tmp;
rep(j, 0, a.length() - 1) {
if (a[j] == '/') {
tmp = a.substr(0, j);
mp.insert((psi) {tmp, 1});
tmp.clear();
}
}
}
rep(i, 1, m) {
cin >> a;
cin.sync();
string tmp;
mp[a] = 0;
rep(j, 0, a.length() - 1) {
if (a[j] == '/') {
tmp = a.substr(0, j);
mp[tmp] = 0;
tmp.clear();
}
}
}
int res = 0;
string ck;
for (psi p : mp) {
// cout<<"**"<<p.first<<" "<<p.second<<'\n';
if (p.second == 1) {
string next_str = p.first.substr(0, ck.length());
if (ck.length() && next_str == ck &&
count(p.first.begin(), p.first.end(), '/') != count(ck.begin(), ck.end(), '/'))
continue; //上层目录已经被删除,无需重复删除
++res;
ck = p.first;
}
}
cout << res << '\n';
}
signed main() {
start;
cin >> T;
while (T--) {
solve();
}
return 0;
}
B. Mine Sweeper II
vice versa为拉丁文,意为“反之亦然”
扫雷游戏,题面概括一下就是将没有雷的格子四周八个格的地雷数量作为这个 non-mine cell
的值,通过对B图最多(m*n)/2
次数的修改,让两图 non-mine cell
值的总和相等。实际上只需要数一下B改成A所需修改次数,若小于等于 (m*n)/2
,则直接输出A图,否则输出取反的A图( m*n
减去一个大于 (m*n)/2
的数,差值必然小于(m*n)/2
,也就是 no solution exists
输出-1的情况是不存在的)。
#include <bits/stdc++.h>
#define rep(x, y, z) for(int x=y;x<=z;x++)
using namespace std;
int a[1001][1001], b[1001][1001];
int main() {
int n, m, cnt = 0, flag = 0;
char c;
cin >> n >> m;
rep(i, 1, n) {
rep(j, 1, m) {
cin >> c;
a[i][j] = c == '.' ? 0 : 1;
}
}
rep(i, 1, n) {
rep(j, 1, m) {
cin >> c;
b[i][j] = c == '.' ? 0 : 1;
cnt += a[i][j] == b[i][j] ? 0 : 1;
}
}
if (cnt > (n * m) / 2) flag = 1;
rep(i, 1, n) {
rep(j, 1, m) cout << ((flag - a[i][j] == 0) ? '.' : 'X');
cout << '\n';
}
return 0;
}
D. Walker
可以分三种情况讨论:
- 其中一人走完全程(一人速度远大于另一人时该方案用时最短)
- 两人相向而行
- 在p1到p2找到一点
mid
,使mid
左右两端路程分别由两人自己走完,通过二分法多次选取mid
点,尽可能使两人所用时间相等
虽然题目要求与答案之间的差值不大于 1e6
,但实际上采用精确度作为二分循环的条件会超时,这里 cnt = 32
是一个能通过牛客和CF上这道题的数据评测的最小值,实际上就算改成 200
也不会超时。
#include <bits/stdc++.h>
#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int T = 1;
// const double esp = 1e-7;
double go(double nn, double p, double v) {
double res = (min(p, nn - p) + nn) / v;
return res;
}
int main() {
start;
cin >> T;
while (T--) {
double n, p1, v1, p2, v2;
cin >> n >> p1 >> v1 >> p2 >> v2;
if (p1 > p2) {
swap(p1, p2);
swap(v1, v2);
}
double ans1 = min(go(n, p1, v1), go(n, p2, v2));
double ans2 = max((n - p1) / v1, p2 / v2);
double l = p1, r = p2, t1, t2, mid;
int cnt = 32;
do {
mid = (l + r) / 2.0;
t1 = go(mid, p1, v1);
t2 = go(n - mid, n - p2, v2);
if (t1 > t2) r = mid;
else l = mid;
} while (--cnt);//abs(t1 - t2) > esp
double ans3 = max(t1, t2);
cout << fixed << setprecision(10) << min(min(ans1, ans2), ans3) << '\n';
}
return 0;
}
I. Sky Garden
(未完待续)