AtCoder Grand Contest 039

时间:2019-11-12
本文章向大家介绍AtCoder Grand Contest 039,主要包括AtCoder Grand Contest 039使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Preface

我发现我现在打AT真的是只会D-Before……

E,F都是抄曲明姐姐的,然后D还是几何画板猜结论做的(证明都是陈指导想的)

看来再这样下去就真的要退役了啊233


A - Connection and Disconnection

JB A题卡我好久(大雾)

我们考虑把一个串的答案先统计出来,填的时候显然尽量向后填。然后判断中间交的地方有哪些要修改

然后WA了,容易发现这样没有充分考虑两个串之间的影响,那么显然可以把两个串接在一起做再判断

然后还是WA了,我们发现只从前往后可能会考虑不充分,因此再尽量往前填一遍算答案即可

然后终于是过了

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=105;
int n,k; long long ans1,ans2; char s[N*3],t[N*3];
int main()
{
    RI i; for (scanf("%s%d",s+1,&k),n=strlen(s+1),i=1;i<=n;++i)
    s[i+n]=s[i+(n<<1)]=t[i]=t[i+n]=t[i+(n<<1)]=s[i];
    if (k==1)
    {
        for (i=2;i<=n;++i) if (s[i]==s[i-1]) s[i]='%',++ans1;
    } else
    {
        for (i=2;i<=(n<<1);++i) if (s[i]==s[i-1]) s[i]='%',++ans1; ans1*=(k>>1);
        if (s[n<<1]==s[1]) ans1+=(k>>1)-1; if (k&1) for (i=(n<<1)+1;i<=3*n;++i)
        if (s[i]==s[i-1]) s[i]='%',++ans1;
    }
    reverse(t+1,t+3*n+1);
    if (k==1)
    {
        for (i=2;i<=n;++i) if (t[i]==t[i-1]) s[i]='%',++ans2;
    } else
    {
        for (i=2;i<=(n<<1);++i) if (t[i]==t[i-1]) t[i]='%',++ans2; ans2*=(k>>1);
        if (t[n<<1]==t[1]) ans2+=(k>>1)-1; if (k&1) for (i=(n<<1)+1;i<=3*n;++i)
        if (t[i]==t[i-1]) t[i]='%',++ans2;
    }
    return printf("%lld",ans1<ans2?ans1:ans2),0;
}

B - Graph Partition

SB题,比A题好写到不知道那里去了

数据范围这么小我们为什么不直接暴力BFS呢?

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=205;
int n,q[N],d[N],col[N],ans; bool g[N][N];
inline char get_digit(void)
{
    char ch; while (ch=getchar(),ch!='0'&&ch!='1'); return ch;
}
inline bool BFS(CI st)
{
    RI H=0,T=1,i; for (q[1]=st,i=1;i<=n;++i) col[i]=-1,d[i]=1e9;
    col[st]=0; d[st]=1; while (H<T)
    {
        int now=q[++H]; for (i=1;i<=n;++i) if (g[now][i])
        {
            if (!~col[i]) col[i]=col[now]^1,d[i]=d[now]+1,q[++T]=i;
            else if (col[now]==col[i]) return 0; else d[i]=min(d[i],d[now]+1);
        }
    }
    for (i=1;i<=n;++i) ans=max(ans,d[i]); return 1;
}
int main()
{
    RI i,j; for (scanf("%d",&n),i=1;i<=n;++i)
    for (j=1;j<=n;++j) g[i][j]=get_digit()-48;
    for (i=1;i<=n;++i) if (!BFS(i)) return puts("-1"),0;
    return printf("%d",ans),0;
}

C - Division by Two with Something

陈指导在证明D题结论的时候我莫名找出了这题的性质,然后就过了。。。

考虑我们统计出有多少种串在经过\(k\)反向操作(就是把前面的数放到后面)后可以变回自己

为了方便统计,我们转化下问题:将一个串全部取反后接在原串后面,然后我们发现进行\(k\)次反向操作后能变回原串当且仅当这个串有一个长度为\(k\)的循环节

我们在挖掘一下性质就会发现\(\frac{2n}{k}\mod 2= 1\),因为若\(\frac{2n}{k}\mod 2= 0\)那么说明这个串的反串与原串相等

然后根据这一条我们容易推导出\(k\)必为偶数,然后我们考虑把\(k\)这个串从\(\frac{k}{2}\)处分开,它也是对称的,证明如下:

原文地址:https://www.cnblogs.com/cjjsb/p/11845367.html