M-SOLUTIONS Programming Contest 2020 题解
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\)和\(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\)或\(-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 题解的更多相关文章
- atcoder Keyence Programming Contest 2020 题解
比赛地址 A 题意:给一个\(n*m\)的初始为白色的矩阵,一次操作可以将一行或一列染成 黑色,问至少染出\(k\)个黑点的最少操作次数. \(n\),\(m\)<=100,\(k\)<= ...
- HHKB Programming Contest 2020 D - Squares 题解(思维)
题目链接 题目大意 给你一个边长为n的正方形和边长为a和b的正方形,要求把边长为a和b的正方形放在长度为n的正方形内,且没有覆盖(可以相邻)求有多少种放法(mod 1e9+7) 题目思路 这个思路不是 ...
- 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 = ...
- 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)\).这就相当于 ...
- 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 ...
- HHKB Programming Contest 2020【ABCE】
比赛链接:https://atcoder.jp/contests/hhkb2020/tasks A - Keyboard 代码 #include <bits/stdc++.h> using ...
- AtCoder AIsing Programming Contest 2020 D - Anything Goes to Zero (二进制,模拟)
题意:给你一个长度为\(n\)的\(01\)串,从高位到低位遍历,对该位取反,用得到的十进制数\(mod\)所有位上\(1\)的个数,不断循环直到为\(0\),输出每次遍历时循环的次数. 题解:根据题 ...
- 【AtCoder】Dwango Programming Contest V题解
A - Thumbnail 题意简述:给出N个数,找出N个数中和这N个数平均值绝对值最小的数 根据题意写代码即可= = #include <bits/stdc++.h> #define f ...
- Atcoder Panasonic Programming Contest 2020
前三题随便写,D题是一道dfs的水题,但当时没有找到规律,直接卡到结束 A - Kth Term / Time Limit: 2 sec / Memory Limit: 1024 MB Score ...
随机推荐
- Redis线程模型的前世今生
一.概述 众所周知,Redis是一个高性能的数据存储框架,在高并发的系统设计中,Redis也是一个比较关键的组件,是我们提升系统性能的一大利器.深入去理解Redis高性能的原理显得越发重要,当然Red ...
- 开源一个简单的react-native 菜单栏抽屉组件,带缩放效果
效果如图所示,源码地址:https://github.com/pofabs/PoSideMenu
- CF1288
A 考虑\(x + 1 = \sqrt{d}\)时在有理域上有最优界. 那我在整数域上附近取三个点取min就行了. // code by fhq_treap #include<bits/stdc ...
- hdu 5552 Bus Routes
hdu 5552 Bus Routes 考虑有环的图不方便,可以考虑无环连通图的数量,然后用连通图的数量减去就好了. 无环连通图的个数就是树的个数,又 prufer 序我们知道是 $ n^{n-2} ...
- Atcoder Typical DP Contest S - マス目(状压 dp+剪枝)
洛谷题面传送门 介绍一个不太主流的.非常暴力的做法( 首先注意到 \(n\) 非常小,\(m\) 比较大,因此显然以列为阶段,对行的状态进行状压.因此我们可以非常自然地想到一个非常 trivial 的 ...
- 生物信息Linux用户创建与配额设置
创建一个新用户,并配置使用. create_usr.sh: #/usr/bin/bash user=$1 password="123" useradd ${user} -g met ...
- R语言与医学统计图形-【11】ggplot2几何对象之散点图
ggplot2绘图系统--几何对象之散点图 以geom开头的函数超过30个.几何对象和标度函数scale密不可分.只有在aes中传入某个变量,scale才能发挥作用. 所谓标度scale,就是图形遥控 ...
- C4.5决策树-为什么可以选用信息增益来选特征
要理解信息增益,首先要明白熵是什么,开始很不理解熵,其实本质来看熵是一个度量值,这个值的大小能够很好的解释一些问题. 从二分类问题来看,可以看到,信息熵越是小的,说明分类越是偏斜(明确),可以理解为信 ...
- Vue3 中有哪些值得深究的知识点?
众所周知,前端技术一直更新很快,这不 vue3 也问世这么久了,今天就来给大家分享下vue3中值得注意的知识点.喜欢的话建议收藏,点个关注! 1.createApp vue2 和 vue3 在创建实例 ...
- JVM结构详解
JVM 结构详解 JVM 结构图 程序计数器(PC 寄存器) 程序计数器的定义 程序计数器是一块较小的内存空间,是当前线程正在执行的那条字节码指令的地址.若当前线程正在执行的是一个本地方法,那么此时程 ...