M-SOLUTIONS Programming Contest 2020 题解

题目质量好高啊,做完感觉好难涨智商了诶。(除了某一道程序又臭又长的F)

A - Kyu in AtCoder

我们可以放很多个if来判断,但这显然不美观。所以,可以观察到,每隔\(200\)点段位都减少\(1\),那么就可以直接通过算式算出了。

程序:

#include<bits/stdc++.h>
using namespace std; int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); int x;
cin>>x;
cout<<10-x/200<<endl; return 0;
}

B - Magic 2

不管卡牌颜色,简单来说就是操作后$$A<B<C$$

并不用考虑这\(K\)次膜法如何分配,反向考虑,最少需要多少次操作使得$$A<B<C$$,这可以贪心的先操作\(B\)再操作\(C\)得到。

程序:

#include<bits/stdc++.h>
using namespace std; int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); int a,b,c,k,n=0;
cin>>a>>b>>c>>k;
while(b<=a)b<<=1,n++;
while(c<=b)c<<=1,n++;
cout<<(n<=k?"Yes\n":"No\n"); return 0;
}

C - Marks

暴力的计算乘积,肯定要溢出的,所以我们来观察一下:(此处把第\(i\)天的等第简单地称作\(G_i\))

\[G_i = A_{i-k+1} \times A_{i-k+2} \times \dots \times A_{i-1} \times A_i
\]

那么,我们可以简单地看出:

\[G_i = G_{i-1} \times A_i \div A_{i-k}
\]

于是只要比较\(G_i\)和\(G_{i-1}\)只需要比较\(A_i\)和\(A_{i-k}\)就好了。程序:

#include<bits/stdc++.h>
using namespace std; int n,k;
int a[200005]; int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i>k){
cout<<(a[i]>a[i-k]?"Yes\n":"No\n");
}
} return 0;
}

D - Road to Millionaire

首先,低价买进,高价卖出,这点生意人的素养我们还是要有的。

我们看到,假设第\(A\)天买入\(C\)手,第\(B\)天卖出\(C\)手,可以转化为:第\(A\)天买入\(C\)手,第\(A+1\)天卖出\(C\)手,第\(A+1\)天买入\(C\)手,第\(A+2\)天卖出\(C\)手,……,第\(B-1\)天买入\(C\)手,第\(B\)天卖出\(C\)手。同时假如这当中有某一天,当天卖出翌日买入是亏损的,那么不买/卖肯定结果更好。

于是,贪心地比较今天和明天的价格并且作出买卖的操作即可获得正确答案。

程序虽然数组叫DP实际上还是贪心:

#include<bits/stdc++.h>
using namespace std; typedef long long ll; int n,a[85];
ll dp[85]; int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
dp[1]=1000;
for(int i=1;i<n;i++){
dp[i+1]=max(dp[i],dp[i]/a[i]*a[i+1]+dp[i]%a[i]);
}
cout<<dp[n]<<endl; return 0;
}

E - M's Solution

首先,建立一条铁轨,虽然不一定要穿过居民区,但是,穿过一定能够获得最优结果。

(感性的)证明:假如铁轨不在居民区上,那么两侧的(走向这条铁轨的)居民数量一定相等,否则可以移动向居民数量更大的一边以获得更优结果,而且,假如两侧居民数量相等,那么任意移动铁轨也是可以的。

那么我们枚举要建立的铁轨就好喽。枚举可能的铁轨是\(O(3^N)\)的(对于每一个居民区,都有放东西向铁轨/南北向铁轨/不放铁轨三种做法),计算答案是\(O(N^2)\)的(可以通过二指针来达到\(O(N)\),但可以卡过去就不用了唷)。题目要求的限定铁轨数量,就在枚举的时候更新对应的答案即可。

程序:(记得考虑初始的两条铁轨)

#include<bits/stdc++.h>
using namespace std; typedef long long ll; int n,x[15],y[15],p[15],D[15],d[15];
ll ans[16]; int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); cin>>n;
for(int i=0;i<n;i++)cin>>x[i]>>y[i]>>p[i];
memset(ans,0x3f,sizeof(ans));
ans[0]=0;
for(int i=0;i<n;i++){
D[i]=min(abs(x[i]),abs(y[i]));
ans[0]+=(ll)p[i]*D[i];
}
for(int s=0;s<1<<n;s++){
for(int t=s;t;t=(t-1)&s){
memcpy(d,D,sizeof(d));
for(int i=0;i<n;i++){
if(s>>i&1){
if(t>>i&1){
for(int j=0;j<n;j++){
d[j]=min(d[j],abs(x[i]-x[j]));
}
}else{
for(int j=0;j<n;j++){
d[j]=min(d[j],abs(y[i]-y[j]));
}
}
}
}
ll cur=0;
for(int i=0;i<n;i++){
cur+=(ll)d[i]*p[i];
}
ans[__builtin_popcount(s)]=min(ans[__builtin_popcount(s)],cur);
}
{
int t=0;
memcpy(d,D,sizeof(d));
for(int i=0;i<n;i++){
if(s>>i&1){
if(t>>i&1){
for(int j=0;j<n;j++){
d[j]=min(d[j],abs(x[i]-x[j]));
}
}else{
for(int j=0;j<n;j++){
d[j]=min(d[j],abs(y[i]-y[j]));
}
}
}
}
ll cur=0;
for(int i=0;i<n;i++){
cur+=(ll)d[i]*p[i];
}
ans[__builtin_popcount(s)]=min(ans[__builtin_popcount(s)],cur);
}
}
for(int i=0;i<=n;i++)cout<<ans[i]<<'\n'; return 0;
}

F - Air Safety

这道题考虑不太难,主要是实现恶心人。(AtCoder你变了!)

首先相撞的飞机大体有两种:

  1. 相向飞行的两架飞机,这个对于每一个横/纵坐标单独考虑就好。
  2. 飞行路线相互垂直的两架飞机,假如相撞,由于速度相等,它们到相撞的点的路程一定是相等的。你可以画出一个直角顶点是相撞点,其他两个顶点是飞机初始位置的等腰直角三角形来,就可以发现它们初始位置一定在同一条斜率为\(1\)或\(-1\)的直线上。那么记录这样的直线所过的向上/下飞行的飞机,再枚举左/右飞行的飞机并查找是否有经过它的直线就好。(先上下还是先左右没什么关系,就是咱喜欢的说)

程序:(还好,不需要离散化)

#include<bits/stdc++.h>
using namespace std; int n,X[200005],Y[200005];
char D[200005];
vector<pair<int,int>> RP,LP;
map<int,set<int>> RL,LL;
vector<int> LR[200005],RR[200005],UC[200005],DC[200005]; int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); cin>>n;
for(int i=0;i<n;i++){
cin>>X[i]>>Y[i]>>D[i];
int &x=X[i],&y=Y[i];
char &d=D[i];
if(d=='U'){
UC[x].emplace_back(y);
LL[y-x].insert(y);
RL[x+y-1919810].insert(y);
}
if(d=='D'){
DC[x].emplace_back(y);
LL[x+y-1919810].insert(y);
RL[y-x].insert(y);
}
if(d=='R'){
RR[y].emplace_back(x);
RP.emplace_back(x,y);
}
if(d=='L'){
LR[y].emplace_back(x);
LP.emplace_back(x,y);
}
}
int ans=1e9;
for(int r=0;r<200000;r++){
sort(LR[r].begin(),LR[r].end());
LR[r].emplace_back(1919810);
sort(RR[r].begin(),RR[r].end());
for(int &x:RR[r]){
int y=*lower_bound(LR[r].begin(),LR[r].end(),x);
if(y!=1919810)ans=min(ans,(y-x)*5);
}
}
for(int c=0;c<200000;c++){
sort(UC[c].begin(),UC[c].end());
sort(DC[c].begin(),DC[c].end());
DC[c].emplace_back(1919810);
for(int &x:UC[c]){
int y=*lower_bound(DC[c].begin(),DC[c].end(),x);
if(y!=1919810)ans=min(ans,(y-x)*5);
}
}
for(pair<int,int> &px:RP){
int y;
if(RL.find(px.second-px.first)!=RL.end() && RL[px.second-px.first].lower_bound(px.second)!=RL[px.second-px.first].end()){
y=*RL[px.second-px.first].lower_bound(px.second);
ans=min(ans,(y-px.second)*10);
}
if(RL.find(px.second+px.first-1919810)!=RL.end() && RL[px.second+px.first-1919810].upper_bound(px.second)!=RL[px.second+px.first-1919810].begin()){
y=*(--RL[px.second+px.first-1919810].upper_bound(px.second));
ans=min(ans,(px.second-y)*10);
}
}
for(pair<int,int> &px:LP){
int y;
if(LL.find(px.second-px.first)!=LL.end() && LL[px.second-px.first].upper_bound(px.second)!=LL[px.second-px.first].begin()){
y=*(--LL[px.second-px.first].upper_bound(px.second));
ans=min(ans,(px.second-y)*10);
}
if(LL.find(px.second+px.first-1919810)!=LL.end() && LL[px.second+px.first-1919810].lower_bound(px.second)!=LL[px.second+px.first-1919810].end()){
y=*LL[px.second+px.first-1919810].lower_bound(px.second);
ans=min(ans,(y-px.second)*10);
}
}
if(ans==1e9)cout<<"SAFE";
else cout<<ans; return 0;
}

M-SOLUTIONS Programming Contest 2020 题解的更多相关文章

  1. atcoder Keyence Programming Contest 2020 题解

    比赛地址 A 题意:给一个\(n*m\)的初始为白色的矩阵,一次操作可以将一行或一列染成 黑色,问至少染出\(k\)个黑点的最少操作次数. \(n\),\(m\)<=100,\(k\)<= ...

  2. HHKB Programming Contest 2020 D - Squares 题解(思维)

    题目链接 题目大意 给你一个边长为n的正方形和边长为a和b的正方形,要求把边长为a和b的正方形放在长度为n的正方形内,且没有覆盖(可以相邻)求有多少种放法(mod 1e9+7) 题目思路 这个思路不是 ...

  3. Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解

    将题意转换为一开始\(t = 0\),第\(i\)个操作是令\(t \leftarrow (a_i + 1) t + (a_i + b_i + 1)\).记\(A_i = a_i + 1, B_i = ...

  4. Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 C题题解

    首先,我们将题目理解成若\(i\)与\(j\)距离恰好为\(3\),则不可能\(p_i \equiv p_j \equiv 1 \space or \space 2 (\bmod 3)\).这就相当于 ...

  5. 2021.7.27--Benelux Algorithm Programming Contest 2020 补提

    I Jigsaw 题目内容: 链接:https://ac.nowcoder.com/acm/contest/18454/I 来源:牛客网 You have found an old jigsaw pu ...

  6. HHKB Programming Contest 2020【ABCE】

    比赛链接:https://atcoder.jp/contests/hhkb2020/tasks A - Keyboard 代码 #include <bits/stdc++.h> using ...

  7. AtCoder AIsing Programming Contest 2020 D - Anything Goes to Zero (二进制,模拟)

    题意:给你一个长度为\(n\)的\(01\)串,从高位到低位遍历,对该位取反,用得到的十进制数\(mod\)所有位上\(1\)的个数,不断循环直到为\(0\),输出每次遍历时循环的次数. 题解:根据题 ...

  8. 【AtCoder】Dwango Programming Contest V题解

    A - Thumbnail 题意简述:给出N个数,找出N个数中和这N个数平均值绝对值最小的数 根据题意写代码即可= = #include <bits/stdc++.h> #define f ...

  9. Atcoder Panasonic Programming Contest 2020

    前三题随便写,D题是一道dfs的水题,但当时没有找到规律,直接卡到结束 A - Kth Term /  Time Limit: 2 sec / Memory Limit: 1024 MB Score ...

随机推荐

  1. 快上车丨直播课“Hello ArkansasUI:初识Slider组件(eTS语言)”来啦!

    11月24日19:00-20:30,Hello HarmonyOS系列课程第二期线上直播,将手把手教你使用最新的ArkUI进行开发,学习eTS语言.Slider组件和Image组件.完成本期直播课的学 ...

  2. 353 stars Java项目!Java小白必看!austin介绍 【第一话】

    有好几个群友问我为什么最近更新变慢了.工作忙是一方面,另一方面是我更新文章的动力确实下降了.近大半年一直在更新的<对线面试官>系列,到现在已经40篇了. 说实话,当时我更新该系列有很大一部 ...

  3. AtCoder Grand Contest 055 题解

    A 赛时直到最后 10min 才做出这个 A 题,之前猜了一个结论一直没敢写,本来不抱啥希望 AC 的结果比赛结束时交了一发竟然 A 了,由此可见我的水平之菜/dk 考虑每次取出字符串开头字符,不妨设 ...

  4. Codeforces 1406E - Deleting Numbers(根分+数论)

    Codeforces 题面传送门 & 洛谷题面传送门 一道个人感觉挺有意思的交互题,本人一开始想了个奇奇怪怪的做法,还以为卡不进去,结果发现竟然过了,而且还是正解( 首先看到这类题目可以考虑每 ...

  5. 洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)

    题面传送门 首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times ...

  6. BZOJ 3043 [Poetize6] IncDec Sequence

    题目描述 给定一个长度为n的数列$a_1,a_2,--,a_n$​,每次可以选择一个区间[l,r],使这个区间内的数都加1或者都减1. 请问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最 ...

  7. Spring-boot -Web开发

    1).创建SpringBoot应用,选中我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来 3).自己编写业务代码: 文件名的功能 x ...

  8. [Linux] 非root安装Lefse软件及其数据分析

    说明 Lefse软件是宏组学物种研究常用软件,一般大家用在线版本即可.但要搭建在Linux集群环境中有点烦,记录一下折腾过程. 安装 这个软件是python2写的,因此假设我已经安装好了较高版本的py ...

  9. ZAQI

    mysql> CREATE TABLE emploee ( -> name CHAR(64) NOT NULL, -> email CHAR(64), -> password ...

  10. git添加新账号

    1,在linux上添加账号 useradd test passwd test usermod -G gitgroup  test  将test账号的组改为和git一样的组gitgroup  git所在 ...