Educational Codeforces Round 125 (Rated for Div. 2)(ABCDE)

Posted 斗奋力努

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 125 (Rated for Div. 2)(ABCDE)相关的知识,希望对你有一定的参考价值。

Educational Codeforces Round 125 (Rated for Div. 2)(ABCDE)

A. Integer Moves


题意:大概是说最初在点(0,0),想要到点(x,y),只能走整数距离(不清楚,根据样例猜),问最少多少步
思路:
目标点就是原点,步数0
目标点与原点的直线距离是整数,步数1
否则步数就是2(先走到同x,再同y)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int x,y;

void solve()
    scanf("%d%d",&x,&y);
    if(x==0&&y==0) puts("0");
    else
        int num=sqrt(x*x+y*y);
        if(num*num==x*x+y*y) puts("1");
        else puts("2");
    


int main()
    int T;scanf("%d",&T);
    while(T--) solve();
    return 0;

B. XY Sequence


题意:构造一个长度为n的序列,序列中每个元素的值 < = B <=B <=B,后一个数 a [ i + 1 ] = a [ i ] + x a[i+1]=a[i]+x a[i+1]=a[i]+x a [ i + 1 ] = a [ i ] − y a[i+1]=a[i]-y a[i+1]=a[i]y,问序列的最大总和是多少
思路:我们知道初始 a [ 0 ] = 0 a[0]=0 a[0]=0,我们每次去找到符合题意的最大的数就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n,B,x,y;

void solve()
    scanf("%lld%lld%lld%lld",&n,&B,&x,&y);
    ll sum=0,now=0;
    for(ll i=1;i<=n;i++)
        ll nu1=now+x;
        ll nu2=now-y;
        if(nu1<=B&&nu2<=B)
            if(nu1>=nu2)
                now=nu1;
                sum+=nu1;
            
            else
                now=nu2;
                sum+=nu2;
            
        
        else if(nu1<=B)
            now=nu1;
            sum+=nu1;
        
        else 
            now=nu2;
            sum+=nu2;
        
    
    printf("%lld\\n",sum);


int main()
    int T;scanf("%d",&T);
    while(T--) solve();
    return 0;

C. Bracket Sequence Deletion


题意:只包含 ′ ( ′ 和 ′ ) ′ '('和')' ()的长度为n的字符串,每次删除前面最短的合法括号序列或回文序列,问最终会操作多少次和最后剩下多少字符
题意很重要,开始读的十分离谱,什么最小剩余的同时的最少操作次数
思路:
我们发现,当前是 ′ ( ′ '(' (,只要后还存在字符,那么都会一起直接删掉。 ( ( 或 ( ) (( 或() ((()
当前是 ′ ) ′ ')' ),后面是 ′ ) ′ ')' ),则构成 ) ) )) ))直接删掉;
而后面如果是 ′ ( ′ '(' (,则一直往后面找,知道找到第一个 ′ ) ′ ')' )或末尾为止。 ) ( ( . . ( ( ) )((..(() )((..(()

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n;
char s[N];

void solve()
    scanf("%d",&n);
    scanf("%s",s+1);
    int use=0,cnt=0;
    for(int i=1;i<=n;)
        if(s[i]=='(')
            if(i!=n) //  "(("或"()"
                cnt++;
                use+=2;
            
            i=i+2;
        
        else
            int pos=i+1;
            int num=0;
            while(pos<=n&&s[pos]=='(')
                pos++;
                num++;
            
            if(pos<=n&&s[pos]==')') //")(((...(()"
                cnt++;
                use+=num+2;
            
            i=pos+1;
        
    
    printf("%d %d\\n",cnt,n-use);


int main()
    int T;scanf("%d",&T);
    while(T--) solve();
    return 0;

D. For Gamers. By Gamers.


题意:
有n种伙伴可以选择,第i种伙伴有 c i , h i , d i ci,hi,di ci,hi,di三个参数,代表选择一个伙伴的花费、每个伙伴的单位时间的攻击力、每个伙伴的生命值。
一共有m个怪物,第j个怪物有 D j , H j Dj,Hj Dj,Hj两个参数,代表每个怪兽的单位时间的攻击力、每个怪兽的生命值。
每一轮我们有C枚金币,我们当前轮只能选择一种伙伴进行战斗,在不超过C枚金币的情况下,我们可以选择多位该类型伙伴,问在没有伙伴阵亡的情况下击败每个怪物的最小花费。 攻击伤害是持续累加的(奇怪)
思路:
我们经过公式转换,我们发现我们可以找到每个金币可以解决的最大怪物乘积???,然后二分答案就行了。
(具体看推导吧)

考虑:
对于第i种伙伴,有ci,hi,di
对于第j个怪物,有Dj,Hj

发现,怪物肯定会十分聪明,只会盯着一个伙伴进行攻击,这样使得我们不满足没有伙伴阵亡的情况,
从而需要增加伙伴数量来加大火力,间接导致花费变高。
我们知道一位伙伴存活时间为: time=hi/Dj, 则我们击败怪物的时间需要严格小于time
设我们需要该类型伙伴数量num,则有: num*time*di>Hj  即num*hi*di>Dj*Hj 
花费为money=num*ci
所以当我们对于花费val元,找到最大的hi*di,就可以解决问题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5,M=1e6+6;
ll n,C,m,f[M]; //f[i]表示花费i元的最大h*d
struct node1ll c,d,h;a[N];
struct node2ll D,H;b[N];

void solve()
    scanf("%lld%lld",&n,&C);
    for(ll i=1;i<=n;i++)
        scanf("%lld%lld%lld",&a[i].c,&a[i].d,&a[i].h);
        f[a[i].c]=max(f[a[i].c],a[i].d*a[i].h);
    
    scanf("%lld",&m);
    for(ll i=1;i<=m;i++) scanf("%lld%lld",&b[i].D,&b[i].H);

    for(ll i=1;i<=C;i++)
        for(ll j=1;j<=C/i;j++)
            f[i*j]=max(f[i*j],f[i]*j);
        
    
    
    for(ll i=1;i<M;i++) f[i]=max(f[i],f[i-1]);

    for(ll i=1;i<=m;i++)
        ll idx=upper_bound(f+1,f+M,b[i].H*b[i].D)-f;
        if(idx>C) printf("-1 ");
        else printf("%lld ",idx);
    
    


int main()
    int T=1;
    while(T--) solve();
    return 0;

E. Star MST

题意:

题意:
有n个节点的完全图,问与节点1相连的所有的权值和等于这n个节点构成的最小生成树的图有多少种。
每条边的权值在[1,k]之间,只要有一条边的权值不同,则是不同的两个图
思路:
初始想成在定节点1相连的边的最大权值和最大权值边的数量去解决,发现会少一些情况。
根据大佬思路:
定义:
d p [ i ] [ j ] dp[i][j] dp[i][j]为所有边权小于等于i的边,已经和1相连的边为j个
我们发现对于边权为i+1的边,我们考虑有l个点与节点1的边为i+1
当前剩下 n − 1 − j n-1-j n1j个点,选其中l个, C [ n − 1 − j ] [ l ] C[n-1-j][l] C[n1j][l]
对于这k个点内部的两两连边,有 l ∗ ( l − 1 ) / 2 l*(l-1)/2 l(l1)/2条边,且值需要大于 > = i + 1 >=i+1 >=i+1, 即 ( k − i + 1 ) ( l − 1 ) / 2 (k-i+1)^(l-1)/2 (ki+1)(l1)/2
对于其他已经与节点1连边的j个点,有 j ∗ l j*l jl条边,且值需要大于 > = i + 1 >=i+1 >=i+1, 即 ( k − i + 1 ) j ∗ l (k-i+1)^j*l (ki+1)Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27