【Codeforces Round #583】A.B.C.D.E

前言

好久没打cf的弟弟重新打cf了,由于fst一题没能上太多分。

ljjq r a t i n g + = 65 rating+=65 1720->1785


A. Optimal Currency Exchange

题意

签到题。

做法

暴力枚举即可。

代码

#include<stdio.h>
int min(int a,int b) {return a<b?a:b;}
int main()
{
    int n,d,e;
    scanf("%d%d%d",&n,&d,&e);
    e = 5*e;
    int ans = n;
    for(int i=0;i<=n/d;i++) ans=min(ans,(n-i*d)%e);
    printf("%d\n",ans);
    return 0;
}

B. Badges

题意

签到题。

做法

枚举男女生人数即可。

代码

#include<stdio.h>
int main()
{
    int b,g,n;
    scanf("%d%d%d",&b,&g,&n);
    int ans = 0;
    for(int i=0;i<=b;i++)
    {
        for(int j=0;j<=g;j++)
        {
            if(i+j==n)
            {
                ans++;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}



C. Bad Sequence

题意

给你一个括号序列,问是否可以最多改变一个括号的位置使原序列变为合法序列。

做法

考虑判断一个括号序列是否合法的方法,就是把(当成1,)当成-1,前缀和之后看是否出现过小于0的前缀和,再判断最后的和是否为0.

这道题同理,我们只需要判断是否出现过小于-1的前缀和,最后判断和是否为0即可。

代码

#include<stdio.h>
const int maxn = 2e5+10;
char str[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",str+1);
    int sum = 0;
    int flag=0;
    for(int i=1;i<=n;i++)
    {
        if(str[i]=='(') sum++;
        else sum--;
        if(sum<-1) flag=1;
    }
    if(sum!=0) flag=1;
    if(flag==0) puts("YES");
    else puts("NO");
    return 0;
}



D. Treasure Island

题意

给你一个地图,地图上有一些点是墙壁,最初你站在(1,1)这个点上,每一步只能向右或者向下,问如果为了不让你走到(n,m)这个点,最少添加几个墙壁。

做法

我们知道答案最大为2,因为我们只需要把(1,2)和(2,1)变成墙壁主角就无法走出去了。所以我们现在要判断的就是是否可以不添加或者添加1个墙壁使(1,1)不能走到(n,m)。
第一种情况只需要判断(1,1)是否可以走到(n,m)即可。
第二种情况我的做法是首先dp求出(1,1)这个点到每一个点(i,j)的方案数dp[i][j],并求出(i,j)这个点到达(n,m)这个点的方案数dp2[i][j]。
然后查找是否存在这样一个点(i,j)使得dp[i][j]*dp2[i][j] = dp[n][m],这个意思也就是说所有方案都要经过(i,j)这个点,我们只要把这个点变为墙即可。

但是由于这道n,m很大,所以需要对方案数取模,赛中用两个常用的质数取模被hack掉了。赛后随机了3个模数就过掉了(sad)。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<vector>
#include<random>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
string str[maxn];
char tmp[maxn];
int mod[10];
static int rand_int()
{
    static std::mt19937 gen((std::random_device())());
    static std::uniform_int_distribution<int> uid(1e8, 1e9);
    return uid(gen);
}
int main()
{
    int n,m;
    for(int i=0;i<10;i++) mod[i] = rand_int();
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%s",tmp);
        str[i] = tmp;
    }
    vector<vector<vector<ll> > > v(10);
    for(int i=0;i<6;i++)
    {
        v[i].resize(n);
        for(int j=0;j<n;j++)
            v[i][j].resize(m);
    }
    for(int i=0;i<3;i++) v[i][0][0]=1;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(str[i][j]=='#') continue;
            if(i>0&&str[i-1][j]=='.')
            {
                for(int k=0;k<3;k++)
                {
                    v[k][i][j]=(v[k][i][j]+v[k][i-1][j])%mod[k];
                }
            }
            if(j>0&&str[i][j-1]=='.')
            {
                for(int k=0;k<3;k++)
                {
                    v[k][i][j]=(v[k][i][j]+v[k][i][j-1])%mod[k];
                }
            }

        }
    }

    for(int i=3;i<6;i++) v[i][n-1][m-1]=1;
    for(int i=n-1;i>=0;i--)
    {
        for(int j=m-1;j>=0;j--)
        {
            if(str[i][j]=='#') continue;
            if(i<n-1&&str[i+1][j]=='.')
            {
                for(int k=3;k<6;k++)
                {
                    v[k][i][j]=(v[k][i][j]+v[k][i+1][j])%mod[k-3];
                }
            }
            if(j<m-1&&str[i][j+1]=='.')
            {
                for(int k=3;k<6;k++)
                {
                    v[k][i][j]=(v[k][i][j]+v[k][i][j+1])%mod[k-3];
                }
            }
        }
    }

    if(v[0][n-1][m-1]==0)
    {
        printf("0\n");
        return 0;
    }
    int flag=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(i==n-1&&j==m-1) continue;
            if(i==0&&j==0) continue;
            int f=0;
            for(int k=0;k<3;k++)
            {
                if(1LL*v[k][i][j]*v[k+3][i][j]%mod[k]!=v[k][n-1][m-1]) f=1;
            }
            if(f==0) flag=1;
        }
    }
    if(flag==0) printf("2\n");
    else printf("1\n");
    return 0;
}



E. Petya and Construction Set

题意

给你2n个点,构造一棵树,对于下标为2i-1的点和下标为2i的点有一个限制d[i],也就是2i-i这个点与2i这个点之间的路径长度要等于d[i]。

做法

首先把所有d从大到小排序,并且按顺序放在一个长度为n的链上,因为保证d非递增。所以我们只要从大到小不断加入每一个点即可,如果当前树链放不下这个关系,那么就延伸这个链,否则就在当前链加一条分支即可。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 2e5+10;
int d[maxn];
struct data
{
    int pos;
    int d;
    bool operator < (const data &y)
    {
        return d>y.d;
    }
}x[maxn];
int f[maxn];
int pos[maxn];
vector<int> v;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        x[i].pos=i*2-1;
        scanf("%d",&x[i].d);
    }
    sort(x+1,x+1+n);
    for(int i=1;i<=n;i++) pos[i] = x[i].pos;
    v.push_back(pos[n]);
    for(int i=1;i<=n-1;i++) printf("%d %d\n",pos[i],pos[i+1]);
    for(int i=1;i<=n;i++)
    {
        int d = x[i].d;
        int tt = i+d-1;
        if(tt<n)
        {
            printf("%d %d\n",x[i].pos+1,pos[tt]);
        }
        else
        {
            int sz=v.size();
            if(n-i+(int)v.size()-1==d-1)
            {
                printf("%d %d\n",x[i].pos+1,v[sz-1]);
                v.push_back(x[i].pos+1);
            }
            else
            {
                printf("%d %d\n",x[i].pos+1,v[d-(n-i)-1]);
            }
        }
    }
    return 0;
}


发布了299 篇原创文章 · 获赞 117 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/100550257