Codeforces Round #604 (Div. 2) (题解)

A. Beautiful String (暴力)

题目链接

题目大意:

给定一个字符串,只有 \(?a\ b\ c\ ?\) ,问是否存在一种将所有的 \(?\) 替换成 \(a\ b\ c\) ,使得任意相邻的字符不同的方法。

大致思路:

其实可以发现问号都可以通过枚举使得其合法,若出现不合法必然除去问好已经不合法,暴力枚举即可。

代码:

点击展开代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
char s[N];
int T;
char c[3]={'a','b','c'};
int main()
{
    //freopen("H:\\c++1\\in.txt","r",stdin);
    //freopen("H:\\c++1\\out.txt","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%s",s+1);
        int len=strlen(s+1);
        for(int i=1;i<=len;i++){
            if(s[i]=='?'){
                    for(int j=0;j<3;j++){
                        if(c[j]!=s[i-1]&&c[j]!=s[i+1]){
                            s[i]=c[j];break;
                        }
                    }
                
            }
        }
        int flag=0;
        for(int i=1;i<len&&flag==0;i++){
            if(s[i]==s[i+1])flag=1;
        }
        if(flag){
            puts("-1");
        }
        else printf("%s\n",s+1);
    }
    return 0;
}

B. Beautiful Numbers (思维)

题目链接

题目大意:

给一个排列,定义 \(m\) 为存在一段连续的 \(1 - m\) 的排列,如 \(\{4,5,1,3,2,6\}\) ,就存在 \({1,3,2}\) ,为 \(3\) 的排列,其就不存在 \(m=2\) 的排列。问对于每一个 \(m\) 判断是否存在 \(1-m\) 的排列。

大致思路:

只要将每一个数字的位置记录下来为 \(pos\) 数组,例如 \(\{4,5,1,3,2,6 \}\)\(pos\) 数组就是 \(\{3,5,4,1,2,6 \}\) 那么我们只要从前往后记录最大值 \(max\) 和最小值 \(min\) ,然后 \(max-min+1==i\) 就是存在 \(1-m\) 的排列。

代码:

点击展开代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
set<int>s; // 用set维护最大值最小值,其实不用那么麻烦
int T;
int a[N];
int pos[N];
int n;
int ans[N];
int main()
{
    //freopen("H:\\c++1\\in.txt","r",stdin);
    //freopen("H:\\c++1\\out.txt","w",stdout);
    scanf("%d",&T);
    while(T--){
        s.clear();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            pos[a[i]]=i;
        }
        for(int i=1;i<=n;i++){
            s.insert(pos[i]);
            auto it=s.begin();
            int v1=*it;
            it=s.end();
            it--;
            int v2=*it;
            if(v2-v1+1==i)ans[i]=1;
            else ans[i]=0;
        }

        for(int i=1;i<=n;i++)printf("%d",ans[i]);
        puts("");
    }
    return 0;
}

C. Beautiful Regional Contest (贪心)

题目链接

题目大意:

\(n\) 个人的解题数,现在在发奖牌,金牌银牌铜牌各 \(g,s,b\) 各,要求金牌解题数大于银牌,\(...\) ,铜牌解题数大于无牌,且 \(g,s,b>0 \ \&\& \ g<s,g<b\) ,要求求出的合法的奖牌数,且最大。

大致思路:

一开始想多了,结果导致卡到了比赛结束。。。其实金牌的数量是确定,那么银牌只要取得g+1,然后通过相同解题数看看银牌最少要取多少个,看后计算铜牌最多能取多少个。判断合法性即可。

代码:

点击展开代码

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int T;
int n;
int p[N];
int id[N],l[N],r[N],sum[N],cnt=0;
int qh(int L,int R){
    return sum[R]-sum[L-1];
}
int main()
{
    //freopen("H:\\c++1\\in.txt","r",stdin);
    //freopen("H:\\c++1\\out.txt","w",stdout);
    scanf("%d",&T);
    while(T--){
        cnt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&p[i]);
        }
        reverse(p+1,p+n+1);
        int temp=p[1];cnt++;l[cnt]=1;
        for(int i=1;i<=n;i++){
            if(p[i]==temp)id[i]=cnt;
            else{
                temp=p[i];
                r[cnt]=i-1;
                cnt++;
                l[cnt]=i;id[i]=cnt;
            }
        }
        r[cnt]=n;
        for(int i=1;i<=cnt;i++)sum[i]=r[i]-l[i]+1,sum[i]=sum[i-1]+sum[i];
        int mx=n/2;
        if(mx<5){
            puts("0 0 0");continue;
        }
        int flag=1;
        int pp=id[n];
        int g=sum[pp]-sum[pp-1];
        int pos=l[pp];
        int s=g+1;
        temp=pos-s;
        if(s+g>=n/2)flag=0;
        int pp1=id[temp];
        int pos1=l[pp1];
        s=pos-pos1;
        int sy=n-mx;
        int pp2=id[sy];
        int pos2=r[pp2]+1;
        pp2++;
        int b=pos1-pos2;
        if(b<=0||s<=0||b<=g||s<=g)flag=0;
        if(flag)printf("%d %d %d\n",g,s,b);
        else puts("0 0 0");
    }
    return 0;
}

D. Beautiful Sequence (枚举)

题目链接

题目大意:

给四个数, \(a,b,c,d\) ,表示 \(a\)\(0\)\(b\)\(1\)\(c\)\(2\)\(d\)\(3\) ,要求将这些数排成一排,使得相邻的数差值为1,输出方案。

大致思路:

可以枚举每一个数字做为开头,然后就选择相邻的数字往后填,如果能填完,那么输出方案即可。因为若存在答案,以4种数字开头必然有一种是可以得到解的。

代码:

点击展开代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int ans[N];
int flag=0;
vector<int>temp;
void dfs(int a,int b,int c,int d,int pos){
    if(a+b+c+d==0){
        flag=1;
        puts("YES");
        for(int v:temp)printf("%d ",v);
            puts("");exit(0);
    }
    if(pos==0&&b)temp.push_back(1),dfs(a,b-1,c,d,pos+1);
    if(pos==1){if(c)temp.push_back(2),dfs(a,b,c-1,d,pos+1);
              else if(a)temp.push_back(0),dfs(a-1,b,c,d,pos-1);}
    if(pos==2){if(d)temp.push_back(3),dfs(a,b,c,d-1,pos+1);
              else if(b)temp.push_back(1),dfs(a,b-1,c,d,pos-1);}
    if(pos==3&&c)temp.push_back(2),dfs(a,b,c-1,d,pos-1);

}
int a,b,c,d;

int main()
{
    //freopen("H:\\c++1\\in.txt","r",stdin);
    //freopen("H:\\c++1\\out.txt","w",stdout);
    scanf("%d%d%d%d",&a,&b,&c,&d);
    flag=0;
    if(flag==0&&a){
        temp.clear();
        temp.push_back(0);
        dfs(a-1,b,c,d,0);
    }
    if(flag==0&&b){
        temp.clear();
        temp.push_back(1);
        dfs(a,b-1,c,d,1);   
    }
    if(flag==0&&c){
        temp.clear();
        temp.push_back(2);
        dfs(a,b,c-1,d,2);
    }
    if(flag==0&&d){
        temp.clear();
        temp.push_back(3);
        dfs(a,b,c,d-1,3);
    }
    if(flag==0)puts("NO");
    return 0;
}

E. Beautiful Mirrors (概率DP)

题目链接

题目大意:

\(n\) 个镜子,每一个镜子有 \(p_i\) 的概率说美丽,现在我从第一个镜子开始问,如果它说美丽,那么我就在下一天再问下一个镜子,如果刚好到了第 \(n\) 个镜子,那么我就会开心。否则我就下一天再从第一个镜子开始问。问我开心需要的天数的期望值。

大致思路:

假设有 \(i\) 个镜子,开心需要的天数为 \(F_i\) ,那么 \(F_i=P_i*(F_{i-1}+1)+(1-P_i)*(F_{i-1}+F_i+1)\)

就是在第 \(F_{i-1}\) 天必然是美丽,现在有 \(P_i\) 的概率是美丽,那么我就直接开心了,就是 \(F_{i-1}+1\) 天,还有剩下的概率,我需要从新开始那么就需要 \(F_{i-1}+F_i+1\) 天了。将式子化简一下就是 \(F_i=(F_{i-1}+1)/P_i\) 循环一遍就行了。(就要概率要除100).

代码:

点击展开代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+10;
const int mod=998244353;
ll ksm(ll a,ll b){
    ll res=1,t=a;
    while(b){
        if(b&1)res=(res*t)%mod;
        t=(t*t)%mod;
        b>>=1;
    }
    return res;
}
int n;
ll p[N],f[N];
int main()
{
    //freopen("H:\\c++1\\in.txt","r",stdin);
    //freopen("H:\\c++1\\out.txt","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&p[i]);
    f[0]=0;
    for(int i=1;i<=n;i++){
        f[i]=((100*(f[i-1]+1)%mod)*ksm(p[i],mod-2)%mod)%mod; //注意爆ll
    }
    printf("%lld\n",f[n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/C-W-K/p/12002523.html