Educational Codeforces Round 56 Div. 2

比赛传送门

感觉这次\(CF\)\(C\)题好简单,做出\(3\)道题+全部\(AC\),涨了29分,摆脱\(pupil\),指日可待!


A.Dice Rollings

这道题最大的难度在理解题意上,只要输出合法的方案即可,所以不要想得太复杂。
我们可以发现,除了\(0,1\)以外,任何自然数都可以用\(2,3\)的和表示出来,那我们直接将点数除以2就好了,相当于我们我们只用\(2,3\)来投出那个数。
这么简单,代码就不放了。

B.Letters Rearranging

题意很简单,让你打乱一个字符串,使打乱后的字符串不为回文串,无解输出\(-1\)
直接\(sort\)字符串,排完序再检查一遍是否为回文串(其实没必要单独再扫一遍,直接判断第一个字符和最后一个字符是否相等即可)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
    int k=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        k=k*10+c-48; c=getchar();
    }
    return k*f;
}
int main(){
    int t=read();
    while(t--){
        string s; cin>>s;
        sort(s.begin(),s.end()); //sort大法好
        int len=s.size()-1; bool flag=0;
        for(int i=0;i<=len/2;i++){
            if(s[i]!=s[len-i]){
                flag=1; break;
            }
        }
        if(flag) cout<<s<<endl;
        else cout<<-1<<endl;
    }
    return 0;
}

C.Mishka and the Last Exam

有一个长度为 \(n\)\(n\) 为偶数)的数列 \(a_{1..n}\)和长度为\(\frac n 2\)的数列\(b\)

\[a_i\le a_{i+1}(1\le i<n)\;,\; b_j=a_j+a_{n-j+1}(1\le j \le \frac n 2 ) \]

现在告诉你 \(n\)和数列\(b\),请求出任意一组 \(a_{1..n}\) (保证有解)

可以贪心的将\(b\)拆分成一个满足条件的尽量小的数和满足条件的尽量大的数。那\(a_i\)最好等于\(a_{i-1}\)\(a_{n-i+1}\)最好等于\(a_{n-i+2}\),但情况并不总是这么完美,那我们只要保证满足其中一个条件就好了,可以发现,这么做是一定有解的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
LL read(){
    LL k=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        k=k*10+c-48; c=getchar();
    }
    return k*f;
}
LL a[200010],ans[200010];
int main(){
    int n=read();
    for(int i=1;i<=n/2;i++) a[i]=read();
    ans[0]=0,ans[n+1]=1000000000000000001LL;
    for(int i=1;i<=n/2;i++){
    	if(a[i]-ans[i-1]<=ans[n-i+2]){
    		ans[i]=ans[i-1],ans[n-i+1]=a[i]-ans[i-1];
        }
        else
          ans[n-i+1]=ans[n-i+2],ans[i]=a[i]-ans[n-i+2];
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";

    return 0;
}

D.Beautiful Graph

当时并不会做,看题解后恍然大悟。

因为只能标\(1,2,3\)三个数,且相连的两个点加起来必须为奇数,那么只有这两种情况\(1-2\;,\;3-2\)。我们可以发现,当这个图中存在一个长度为奇数的环的时候是肯定无解的,换句话说,当且仅当这张图是一张二分图的时候有解

这就启发我们了,当有解的时候,我们还可以发现,当一个点 点权为\(2\)且每有一条出边的时候,当前的方案数是要\(\times 2\)的,因为\(2\)可以连\(1\)\(3\);反之,方案数不变,因为\(1,3\)只能去连\(2\)

到这里,思路就很清晰了,对于每一个连通块,我们跑一遍二分图染色,记录下两部分的点的个数,分别计为\(s_1,s_2\),那么这个连通块的方案数为\(2^{s_1}+2^{s_2}\)(因为起始点既可以标\(1\)\(3\),也可以标\(2\),这两种方案会导致标\(2\)的点发生变化,所以要将方案数相加),再将每个连通块的方案数相乘就好了(乘法原理)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 998244353
#define LL long long
using namespace std;
struct zzz{
    int t,nex;
}e[300010<<1]; int head[300010],tot;
inline void add(int x,int y){
    e[++tot].t=y;
    e[tot].nex=head[x];
    head[x]=tot;
}
int vis[300010];
LL sum[5],ans;
bool dfs(int x){
    for(int i=head[x];i;i=e[i].nex){
        if(vis[e[i].t]==-1){
            vis[e[i].t]=(vis[x]^1);
            if(!dfs(e[i].t)) return 0;;
        }
        else{
            if(vis[e[i].t]==vis[x])
              return 0;
        }
    }
    sum[vis[x]]++;
    return 1;
}
LL qpow(LL b,LL p){
    LL ans=1;
    while(p){
        if(p&1) ans=(ans*b)%mod;
        b=(b*b)%mod;
        p>>=1;
    }
    return ans;
}
inline int read(){
    int k=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
      k=k*10+c-48,c=getchar();
    return k*f;
}
int main(){
    int t=read();
    qwq:
    while(t--){
        bool flag=0;
        ans=1; tot=0;
        int n=read(),m=read();
        for(int i=0;i<=n;i++) vis[i]=-1,head[i]=0;
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            add(x,y); add(y,x);
        }
        for(int i=1;i<=n;i++){
            sum[0]=sum[1]=0;
            if(vis[i]==-1){
                vis[i]=1;
                if(!dfs(i)){
                    flag=1; printf("0\n"); goto qwq;
                }
                else
                  ans=(ans*(((qpow(2,sum[0]))%mod+qpow(2,sum[1]))%mod))%mod;
            }
        }
        if(!flag) printf("%lld\n",ans);
    }


    return 0;
}
posted @ 2019-11-14 09:54  MorsLin  阅读(121)  评论(0编辑  收藏  举报