20201104大模拟(一)
开错题了我吐了,赛后A一发过,绝了
B是什么deng西,我得有一段时间不想看到植物大战僵尸了,有一些边界问题
C是在计算的过程中的大模拟
D是思维,
总体来说其实还好,不要怕的,就还好
“一道题WA了五发以上其实就没有出的必要了”
自己想想为什么会打成这个样子好不好
A - Try and Catch
题目真的有点长,还是要耐心阅读理解吧,
只有一个throw,刚开始以为有好多,并且觉得空格挺难搞的就先没做,其实没啥坑的直接冲就完事
#include <bits/stdc++.h>
using namespace std;
struct node {
int pos1;
int pos2;
string a;
string b;
};
stack<int> tryy;
vector<node> catchh;
string throww = "";
int idx;
bool cmp(node x, node y) {
return x.pos1 < y.pos1;
}
int main() {
int n;
cin >> n;
getchar();
for(int i = 1; i <= n; ++ i) {
string s;
getline(cin, s);
int len = s.length();
for(int j = 0; j < len; ++ j) {
if(s[j] == ' ') continue;
if(s[j] == 't') {
if(s[j + 1] == 'r') { // try
tryy.push(i);
}
else { // throw
int k = j + 1;
for(; k < len; ++ k) {
if(s[k] == '(') break;
}
++ k;
for(; k < len; ++ k) {
if(s[k] != ' ') break;
}
for(; k < len; ++ k) {
if(s[k] == ' ' || s[k] == ')') break;
throww = throww + s[k];
}
idx = i;
}
break;
}
if(s[j] == 'c') { // catch
string aa = "";
int k = j + 1;
for(; k < len; ++ k) {
if(s[k] == '(') break;
}
++ k;
for(; k < len; ++ k) {
if(s[k] != ' ') break;
}
for(; k < len; ++ k) {
if(s[k] == ' ' || s[k] == ',') break;
aa = aa + s[k];
}
string bb = "";
for(; k < len; ++ k) {
if(s[k] == '\"') break;
}
++ k;
for(; k < len; ++ k) {
if(s[k] == '\"') break;
bb = bb + s[k];
}
//cout << i << " " << aa << " " << bb << endl;
int pos1 = tryy.top();
tryy.pop();
catchh.push_back({pos1, i, aa, bb});
break;
}
}
}
sort(catchh.begin(), catchh.end(), cmp);
int siz = catchh.size();
// cout << "---- catchh :\n" ;
// for(auto x : catchh) {
// cout << x.pos1 << " " << x.pos2 << " " << x.a << " " << x.b << endl;
// }
//
// cout << "\n\n";
// cout << "idx :" << idx << endl;
bool f = 0;
for(int i = siz - 1; i >= 0; -- i) {
if(f) break;
node tmp = catchh[i];
//cout << tmp.pos1 << " " << tmp.pos2 << endl;
if(tmp.pos1 < idx && tmp.pos2 > idx) {
//cout << throww << " " << tmp.a << endl;
//cout << (tmp.a == throww) << endl;
if(tmp.a == throww) {
cout << tmp.b ;
f = 1;
break;
}
}
}
if(!f) {
cout << "Unhandled Exception";
}
return 0;
}
B - I, zombie
植物大战僵尸,开错题目了,
一些边界问题
- 第一个是土豆雷(这个赛时就想到了(比较后面才想到的
- 有五十多个豌豆射手,或者说对于僵尸的血量可以是负的这件事的理解上面,是知道的,但是在处理过程中有个地方漏掉了,(
刚开始的思路是模拟每一段,每一段要么是MPPPPPPP
要么是MMMMM
就大概是两种,还有一些特殊情况比如PPPPP
,但是其实可以归进去
对于每一段,他的左边有多少个豌豆,当前段要走几步什么的进行模拟(二分
但是关于僵尸血量可以是负的这件事,感觉可以换一种思路进行模拟,
还是要二分
最后一个位置是直接到达的,其他所有位置都要先走一步才能到达
MPMPMPMPMPMPMPM
12
60个豌豆还是处理错了
PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPMMMMMMMMMM
82
还是上面这个60个豌豆的样例,如果是前面全是P, 尸体可以骗土豆雷,但是去吃脑子的时候不能是尸体~~((?? 有点不确定了,~~(对的,但是不是这里的问题
这是第二次重码了,准备开始第三次
WA 也许哪天有心情可以改一改
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int sum[maxn];
bool judge(int leff, int p, int x, bool f) {
if(x == 0) return 0;
//if(p == 0) return 1;
if(!f) {
int z = x;
int hp = 50;
if(p) {
for(int i = p; i > 0; -- i) {
hp -= leff + i;
if(hp <= 0) {
z --;
hp = 50;
}
if(z <= 0) return 0;
int pea = 10;
while(pea > 0) {
pea -= z;
hp -= leff + i;
if(hp <= 0){
z --;
hp = 50;
}
if(z <= 0) return 0;
}
}
}
else {
if(x >= 2) return 1;
else return 0;
}
}
else {
int z = x;
int hp = 50;
if(p) {
int pea = 10;
while(pea > 0) {
pea -= z;
hp -= leff + p;
if(hp <= 0){
z --;
hp = 50;
}
if(z <= 0) return 0;
}
}
else {
if(x) return 1;
else return 0;
}
for(int i = p - 1; i > 0; -- i) {
hp -= leff + i;
if(hp <= 0) {
z --;
hp = 50;
}
if(z <= 0) return 0;
int pea = 10;
while(pea > 0) {
pea -= z;
hp -= leff + i;
if(hp <= 0){
z --;
hp = 50;
}
if(z <= 0) return 0;
}
}
}
return 1;
}
int main () {
int T;
cin >> T;
int cas = 0;
while(T --) {
++ cas;
printf("Case %d: ", cas);
string s;
cin >> s;
int n = s.size();
if(s[0] == 'P') sum[0] = 1;
else sum[0] = 0;
for(int i = 1; i < n; ++ i) {
sum[i] = sum[i - 1] + (s[i] == 'P' ? 1 : 0);
}
bool f = 1;
int cntp = 0;
int tot = 0;
for(int i = n - 1; i >= 0; -- i) {
if(s[i] == 'M') {
cout << "--------- cntp :" << cntp << ' ' << f << endl;
int l = 0, r = 200000, ans;
while(l <= r) {
int mid = (l + r) >> 1;
if(judge(sum[i], cntp, mid, f)) {
ans = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
cout << ans << endl;
tot += ans;
f = 0;
cntp = 0;
}
else {
cntp ++;
}
}
//cout << tot << endl;
//cout << cntp << endl;
if(cntp > 0) {
int l = 0, r = 200000, ans;
while(l <= r) {
int mid = (l + r) >> 1;
if(judge(0, cntp, mid, f)) {
ans = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
tot += ans;
}
if(s[0] == 'M') tot ++;
cout << tot << endl;
}
}
我要按网上思路来le,,可恶 十一点了
0:17 按网上别人的代码流程来的,没啥意思说实话,不过这样写不容易出错,大体思路是一样的,
#include <bits/stdc++.h>
using namespace std;
int step;
bool judge(int pnum, int cnt, int znum) {
int st = step;
int php = 10, zhp = 50;
while(cnt > 0 && znum > 0) {
if(st > 0) {
st --;
zhp -= pnum;
}
else {
php -= znum;
zhp -= pnum;
}
if(php <= 0) {
php = 10;
pnum --; cnt --;
st = 1;
}
if(zhp <= 0) {
zhp = 50;
znum --;
}
}
if(cnt <= 0 && znum > 0) return 1;
else return 0;
}
int getRes(int pnum, int cnt) {
int l = 1, r = 200000, ans;
while(l <= r) {
int mid = (l + r) >> 1;
if(judge(pnum, cnt, mid)) {
ans = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
return ans;
}
int main() {
int T;
cin >> T;
int cas = 0;
while(T --) {
++ cas;
printf("Case %d: ", cas);
string s;
cin >> s;
int n = s.size();
int pnum = 0;
int mnum = 0;
for(int i = 0; i < n; ++ i) {
if(s[i] == 'P') pnum ++;
else mnum ++;
}
int ans = 0;
-- n;
if(s[n] == 'M') {
ans ++;
-- n;
step = 2;
}
else step = 1;
while(n >= 0) {
if(s[n] == 'M') {
if(step > 1) {
step --;
if(pnum >= 50) ans ++;
continue;
}
-- n;
mnum --;
ans ++;
step = 2;
}
else {
int cnt = 0;
for(int i = n; n >= 0; -- i) {
if(s[i] == 'P') cnt ++;
else break;
}
int res = getRes(pnum, cnt);
//cout << pnum << " " << cnt << " " << res << endl;
pnum -= cnt;
ans += res;
n -= cnt + 1;
step = 2;
}
}
if(s[0] == 'M') ans ++;
cout << ans << endl;
}
return 0;
}
C - Broken Watch
刚开始没有题面(),其实不是很难的,
小数据手模找一下规律分奇偶推出两个公式
有个对 2 64 2 ^ {64} 264的取模,unsigned long long 的自然溢出
然后有个除法,刚开始直接除然后wa了,后来考虑到有取模问题就需要用到逆元啥的,码了一个扩展欧几里得,但是发现
2
64
2^{64}
264其实取不到啊,ull
是
2
64
−
1
2 ^ {64} - 1
264−1
于是只能在做的过程中先除掉,分类分死我了
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
//ull mod;
//
//ull exgcd(ull a, ull b, ull & x, ull & y) {
// if(b == 0) {
// x = 1, y = 0;
// return a;
// }
//
// ull d = exgcd(b, a % b, y, x);
//
// y -= (a / b) * x;
//
// return d;
//}
int main() {
ull a, b, c, n;
cin >> a >> b >> c >> n;
int cnt = 1;
if(a == b && a == c) {
cnt = 3;
}
else if(a == b || a == c || b == c){
cnt = 2;
}
ull ans;
if(n <= 2) {
cout << 0 ;
return 0;
}
if(n & 1) {
if(cnt == 1)
ans = n * (1ull + (n / 2)) * (n / 2) ;
else if(cnt == 2) {
if(!((n / 2) & 1)) {
ans = n * (1ull + (n / 2)) * (n / 4);
}
else {
ans = n * ((1ull + (n / 2)) / 2) * (n / 2);
}
}
else if (cnt == 3) {
if(!((n / 2) & 1)) {
if(n % 3 == 0)
ans = (n / 3) * (1ull + (n / 2)) * (n / 4);
else if((1ull + (n / 2)) % 3 == 0){
ans = n * ((1ull + (n / 2)) / 3) * (n / 4);
}
else if((n / 4) % 3 == 0){
ans = n * (1ull + (n / 2)) * (n / 12);
}
}
else {
//ans = n * ((1ull + (n / 2)) / 2) * (n / 2)
if(n % 3 == 0)
ans = (n / 3) * ((1ull + (n / 2)) / 2) * (n / 2);
else if((1ull + (n / 2)) % 3 == 0){
ans = n * ((1ull + (n / 2)) / 6) * (n / 2);
}
else if((n / 4) % 3 == 0){
ans = n * ((1ull + (n / 2)) / 2) * (n / 6);
}
}
}
}
else {
if(cnt == 1)
ans = n * ((2ull + (n / 2)) * (n / 2 - 1)+ (n - 2));
else if(cnt == 2) {
if(!(n & 1)) {
ans = (n / 2) * ((2ull + (n / 2)) * (n / 2 - 1)+ (n - 2));
}
else {
ans = n * (((2ull + (n / 2)) * (n / 2 - 1) + (n - 2)) / 2);
}
}
else if(cnt == 3) {
if(!(n & 1)) {
if((n / 2) % 3 == 0)
ans = (n / 6) * ((2ull + (n / 2)) * (n / 2 - 1)+ (n - 2));
else
ans = (n / 2) * (((2ull + (n / 2)) * (n / 2 - 1)+ (n - 2)) / 3);
}
else {
if(n % 3 == 0)
ans = (n / 3) * (((2ull + (n / 2)) * (n / 2 - 1) + (n - 2)) / 2);
else
ans = n * ((((2ull + (n / 2)) * (n / 2 - 1) + (n - 2)) / 2) / 3);
}
}
}
cout << ans;
return 0;
}
D - A Simple Stone Game
思维,其实感觉不是大模拟
在为什么要分解质因数这里刚开始脑子de牢想了一会
还好
#include <bits/stdC++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll a[maxn];
vector<ll> nums;
int n;
ll getRes(ll x) {
nums.clear();
ll sum = 0;
for(int i = 0; i < n; ++ i) {
if(a[i] % x == 0) continue;
ll num = a[i] % x;
nums.push_back(num);
sum += num;
}
sort(nums.begin(), nums.end());
int siz = nums.size();
ll res = 0;
for(int i = siz - 1; i >= 0; -- i) {
ll tmp = nums[i];
res += x - tmp;
sum -= x;
if(sum <= 0) break;
}
return res;
}
int main() {
int T;
cin >> T;
while(T --) {
//int n;
cin >> n;
ll sum = 0;
ll mx = 0;
for(int i = 0; i < n; ++ i) {
cin >> a[i];
sum += a[i];
mx = max(mx, a[i]);
}
ll ans = sum - mx;
//cout << sum << " " << mx << endl;
for(ll i = 2; i <= sum / i; ++ i) {
if(sum % i == 0) {
//cout << "i :" << i << endl;
ll res = getRes(i);
//cout << "----" << i << " " << res << endl;
ans = min(ans, res);
while(sum % i == 0) sum /= i;
}
}
if(sum > 1) {
ll res = getRes(sum);
//cout << "----" << sum << " " << res << endl;
ans = min(ans, res);
}
cout << ans << endl;
}
return 0;
}