AtCoder ABC 243
A Shampoo(水)
Description:
三个人轮流用水 请问用到谁的时候水就用完了
Method:
水题 但是因为%和/用错了 导致蛙了好几次
分类讨论 如果一轮用不完 就取余再判断 如果一轮用得完 直接判断
Code:
void solve()
{
int v, a, b, c;
cin >> v >> a >> b >> c;
int sum = a + b + c;
int t = v % sum;
if(sum > v)
{
if(a > v) {cout << "F"; return;}
else if(a + b > v) {cout << "M"; return;}
else {cout << "T"; return;}
}
else
{
if(a > t) {cout << "F"; return;}
else if(a + b > t) {cout << "M"; return;}
else {cout << "T"; return;}
}
}
B Hit and Blow(水)
Description:
给定两个数组a b 判断数组中位置和数值都相同的个数 & 位置不同数值相同的个数
Method:
map查重咯
Code:
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
for(int i = 1; i <= n; i++)
cin >> b[i];
int res1 = 0, res2 = 0;
for(int i = 1; i <= n; i++)
mp[a[i]] = true;
for(int i = 1; i <= n; i++)
if(mp[b[i]]) res2 ++;
for(int i = 1; i <= n; i++)
if(a[i] == b[i]) res2 --, res1 ++;
cout << res1 << '\n' << res2;
}
C Collision 2(水)
Description:
给出n个点的坐标和行进方向 若是两个坐标会相遇 输出yes
Method:
显然 判断yes更简单 我们进行排序 然后对相同纵坐标进行判断 若是左边的点向右走 右边的点向左走 YES
Code:
struct node
{
int x, y, op; // op 0 L op 1 R
bool operator< (const node & E) const
{
if(y == E.y) return x < E.x;
return y < E.y;
}
}q[200010];
void solve()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
cin >> q[i].x >> q[i].y;
string s;
cin >> s;
for(int i = 0; i < n; i++)
{
if(s[i] == 'L') q[i].op = 0;
else q[i].op = 1;
}
sort(q, q + n);
for(int i = 1; i < n; i++)
{
if(q[i].y != q[i - 1].y) continue;
if(q[i - 1].op == 1 && q[i].op == 0)
{
puts("Yes"); return;
}
}
puts("No");
}
D Moves on Binary Tree(二叉树)
Description:
给出当前节点 对节点进行一个1e6的操作 每次操作选择移动到他的父节点 左儿子 或者右儿子
节点数会在longlong的极限左右 但保证最终答案一定在longlong范围内
Method:
因为给的节点数字很大 用高精度模拟会TLE 正常模拟会爆long
我的猜想就是消除题目中的U 和 L 但是经验证不对
因为R是 x * 2 + 1 而U是 x / 2 这一点就带来了误差
1 消除相邻的UL 和 RL 因为R仅仅是加了一次1 这时直接除2并不会造成影响 且保证答案在LL内
2 将节点化为二进制串表示并进行二进制的计算 然后再转回十进制
Code:
stack<char> stk;
void solve()
{
int n;
LL x;
cin >> n >> x;
string s;
cin >> s;
int l, r;
for(int i = 0; i < n; i++)
{
if(!stk.empty())
{
if((s[i] == 'U' && (stk.top() == 'L' || stk.top() == 'R'))) stk.pop();
else stk.push(s[i]);
}
else stk.push(s[i]);
}
string res;
while(stk.size()) res += stk.top(), stk.pop();
reverse(res.begin(), res.end());
for(int i = 0; i < res.size(); i++)
{
if(res[i] == 'L') x *= 2;
else if(res[i] == 'R') x = x * 2 + 1;
else x /= 2;
}
cout << x << '\n';
}
string get_(LL x)//十转二
{
string res;
while(x)
{
res += '0' + (x % 2);
x /= 2;
}
reverse(res.begin(), res.end());
return res;
}
void solve()
{
int n; LL x;
cin >> n >> x;
string s;
cin >> s;
string nums = get_(x);
for(int i = 0; i < n; i++)
{
if(s[i] == 'R') nums += '1';
else if(s[i] == 'L') nums += '0';
else nums.erase(nums.end() - 1);
}
int m = nums.size();
LL res = 0;
reverse(nums.begin(), nums.end());
for(int i = 0; i < m; i++)//二转十
{
LL t = nums[i] - '0';
res += t * (1LL << i);
}
cout << res << '\n';
}
E Edge Deletion(图论 + 构造)
Description:
给定n个顶点m条边 保证不会出现重边和自环
请尝试删去最多的边(在不影响原有两点之间路径长度以及保持图的联通)
Method:
原有两点路径看起来很复杂 其实就是对最短路查重 若是如样例一一般 最短路有两条 且权相同 可以删去
我们先通过flody跑一遍最短路 然后遍历两个顶点和中转点询问是否存在最短路重复
Code:
int n, m;// point n edge m
int a, b;
LL c;
LL mp[310][310];
void solve()
{
cin >> n >> m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
mp[i][j] = (i == j) ? 0 : INF;
for(int i = 0; i < m; i++)
{
cin >> a >> b >> c;
mp[a][b] = c;
mp[b][a] = c;
}
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
int res = 0; //保留的边数
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(i != j)
{
int rem = 1;
for(int k = 1; k <= n; k++)
if(i != k && j != k && mp[i][j] == mp[i][k] + mp[k][j])
//存在这种情况的时候 可以去掉一个边
rem = 0;
res += rem;
}
cout << m - res / 2 << '\n'; //因为正反都扫了一遍 所以保留的边数/2
}
F Lottery(不会)
Description:
Method:
Code:
G Sqrt(DP + 前缀和 + 优化)
Description:
Method:
尽力去听了 但是还是不懂 放一串代码吧
Code:
#include <bits/stdc++.h>
using namespace std;
//多组输入的初始化
//判断是否需要LL
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define endl '\n'
#define ms(x, y) memset(x, y, sizeof x)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1000010;
LL dp[N], pre[N];
LL is_sqrt(LL x)
{
LL sqrtX = sqrt(x) - 1;
while(sqrtX + 1 <= x / (sqrtX + 1)) sqrtX ++;
return sqrtX;
}
void solve()
{
cin >> x;
LL x2 = is_sqrt(x);
LL x4 = is_sqrt(x2);
LL res = 0;
for(int i = 1; i <= x4; i++)
res += (x2 - 1LL * i * i + 1) * dp[i];
cout << res << '\n';
}
int main()
{
ios;
dp[1] = 1;
pre[1] = 1;
for(int i = 2; i <= N; i++)
dp[i] = pre[is_sqrt(i)], pre[i] = pre[i - 1] + dp[i];
int _;
cin >> _;
while(_--) solve();
return 0;
}