AtCoder Beginner Contest 160

Posted zdragon1104

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 160相关的知识,希望对你有一定的参考价值。

传送门

A - Coffee

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char s[10];
int main() {
    //freopen("in.txt","r",stdin);
    scanf("%s",s);
    if(s[2]==s[3]&&s[4]==s[5]) printf("Yes
");
    else printf("No
");
    return 0;
}
A.cpp

B - Golden Coins

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    //freopen("in.txt","r",stdin);
    ll x;
    scanf("%lld",&x);
    printf("%lld
",x/500*1000+(x%500)/5*5);
    return 0;
}
B.cpp

C - Traveling Salesman around Lake

题意:在一个周长为K的圆形中,有N个房子距离最北边的距离为Ai(顺时针),可以任意选一个房子作为起点,求访问完N个房子的最小距离。

数据范围:$2 leq K leq 10^{6},2 leq N leq 2 imes 10^{5}$

题解:最优解肯定是沿一个方向的,环形可以将原序列扩展一倍,遍历序列每一对下标相差N的位置的差值,最小值即为答案。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
int a[N<<1];
int main() {
    //freopen("in.txt","r",stdin);
    int k,n;
    scanf("%d%d",&k,&n);
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
        a[i+n]=a[i]+k;
    }
    int ans=1e9;
    for(int i=0;i<n;i++) {
        ans=min(ans,a[i+n-1]-a[i]);
    }
    printf("%d
",ans);
    return 0;
}
C.cpp

 D - Line++

题意:给一个图,满足任意i=1,2,...,N-1,i和i+1有连边,且X和Y有连边,对于k=1,2,...,N-1,求最短距离为k的点对数量。

数据范围:$3 leq N leq 2 imes 10^{3},X+1 < Y$

题解:暴力求每个点对的最短距离,要么就是i,j直达,要么就是i到X,X到Y,Y到j,取小即可。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e3+5;
int a[N];
int main() {
    //freopen("in.txt","r",stdin);
    int n,x,y;
    scanf("%d%d%d",&n,&x,&y);
    for(int i=1;i<=n;i++) {
        for(int j=i+1;j<=n;j++) {
            int t=min(j-i,abs(i-x)+abs(j-y)+1);
            a[t]++;
        }
    }
    for(int i=1;i<n;i++) {
        printf("%d
",a[i]);
    }
    return 0;
}
D.cpp

 E - Red and Green Apples

题意:给A个红苹果,B个绿苹果,C个无色苹果,每个苹果都有美味值,可以将无色苹果涂成任意颜色,求吃X个红苹果和Y个绿苹果的最大美味值。

数据范围:$1leq X leq A leq 10^{5},1leq Y leq B leq 10^{5},1leq C leq 10^{5}$

题解:按美味值降序,有色苹果能吃就吃并将X或Y减1,无色苹果直接吃,计数器加1,若计数器等于X+Y代表不能吃了,直接退出。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
struct P {
    int val,id;
    bool operator <(const P &t)const {
        if(val!=t.val) return val>t.val;
        return id<t.id;
    }
}p[N*3];
int main() {
    //freopen("in.txt","r",stdin);
    int x,y,a,b,c;
    scanf("%d%d%d%d%d",&x,&y,&a,&b,&c);
    for(int i=0,d;i<a;i++) {
        scanf("%d",&d),p[i]={d,1};
    }
    for(int i=0,d;i<b;i++) {
        scanf("%d",&d),p[i+a]={d,2};
    }
    for(int i=0,d;i<c;i++) {
        scanf("%d",&d),p[i+a+b]={d,0};
    }
    a=a+b+c;
    sort(p,p+a);
    ll ans=0;
    int t=0;
    for(int i=0;i<a;i++) {
        if(p[i].id==1) {
            if(x) x--,ans+=p[i].val;
        }
        else if(p[i].id==2) {
            if(y) y--,ans+=p[i].val;
        }
        else {
            t++,ans+=p[i].val;
        }
        if(t==x+y) break;
    }
    printf("%lld
",ans);
    return 0;
}
E.cpp

F - Distributing Integers

题意:给一棵N个节点的无根树,对于k=1,2,...,N,将1写在节点k上,然后2~n依次写在与有值的节点相邻的节点上,求最后有多少种写法。(对1e9+7取模)

数据范围:$2leq N leq 2 imes 10^{5}$

题解:问题其实就是以k为根节点的树的拓扑序列个数,设szi为i子树的大小,答案为$frac{n!}{prod sz_{i}}$。

首先1~n的全排列有n!种情况,对于每个节点x,x要在x子树的其它节点之前,相当于在之前的基础上除szx

考虑u,v相连,根节点从u转移到v的情况,可以发现只有szu和szv发生变化。那么可以先算出以1为根节点的个数,然后转移即可。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
const int MD=1e9+7;
vector<int> G[N];
int f[N],ans[N];
int n,a,b;
int quick_pow(int x,int y) {
    int ans=1;
    while(y) {
        if(y&1) ans=1LL*ans*x%MD;
        y>>=1;
        x=1LL*x*x%MD;
    }
    return ans;
}
void dfs(int u,int fa) {
    for(auto v:G[u]) {
        if(v==fa) continue;
        dfs(v,u);
        f[u]+=f[v];
    }
    f[u]++;
}
void cal(int u,int fa) {
    for(auto v:G[u]) {
        if(v==fa) continue;
        ans[v]=1LL*ans[u]*quick_pow(f[v],MD-2)%MD*(n-f[v])%MD;
        cal(v,u);
    }
}
int main() {
    //freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<n;i++) {
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs(1,-1);
    ans[1]=1;
    for(int i=1;i<=n;i++) {
        ans[1]=1LL*ans[1]*f[i]%MD;
    }
    cal(1,-1);
    int t=1;
    for(int i=1;i<=n;i++) t=1LL*t*i%MD;
    for(int i=1;i<=n;i++) {
        printf("%d
",1LL*t*quick_pow(ans[i],MD-2)%MD);
    }
    return 0;
}
F.cpp

 

以上是关于AtCoder Beginner Contest 160的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242