Codeforces Round #306 div 2 solution

  这场总的来说打的还行吧,不过fst了一题很郁闷。。感觉从pkusc回来看CF的英文题面就和看中文一样。。出AB的速度我觉得还是不错的。。没什么难题完全可以AK的,但是构造题有细节理不清,要加强处理复杂的关系的能力。。

A:给一个字符串,问你能不能找到不重复的”BA”和”AB”
我的做法是先找AB再找BA和先找BA再找AB各做一次。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<cstring>
#define inf 0x3fffffff
#define N 100005
using namespace std;
char s[N];
int i,len;
bool f;
int main()
{
    scanf("%s",s+1);
    f=false;len=strlen(s+1);
    for (i=1;i<len-2;i++) 
        if (s[i]=='A'&&s[i+1]=='B')
        {
            for (int j=i+2;j<=len;j++) if (s[j]=='B'&&s[j+1]=='A') f=true;
            break;
        }
    for (i=1;i<len-2;i++) 
        if (s[i]=='B'&&s[i+1]=='A')
        {
            for (int j=i+2;j<len;j++) if (s[j]=='A'&&s[j+1]=='B') f=true;
            break;
        }
    if (f) printf("YES\n");else printf("NO\n");
}


B:给n个数,求和在 [l,r] 且极差 x 的子集数量。。
n15 ,直接暴力枚举所有情况。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<cstring>
#define inf 0x3fffffff
#define N 
using namespace std;
int n,l,r,xx,i,ans=0,a[20];
void dfs(int x,int sum,int mi,int mx)
{
    if (x>n)
    {
        if (l<=sum&&r>=sum&&mx-mi>=xx) ans++;
        return;
    }
    if (sum==0) dfs(x+1,a[x],a[x],a[x]);else dfs(x+1,sum+a[x],mi,a[x]);
    dfs(x+1,sum,mi,mx);
}
int main()
{
    scanf("%d%d%d%d",&n,&l,&r,&xx);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    dfs(1,0,0,0);
    printf("%d\n",ans);
}

C:给一个数字字符串,求一个不含前导0的子序列使子序列构成的数被8整除。
这题一开始想错了用了错误的方法。。然而CF的pretest弱得不行竟然水过去了,还没人hack我。。结果FST。。考虑一个四位及以上的解x,由于1000%8==0,所以x%1000同样也是一个解,所以若有解必然存在小于1000的解,直接暴力枚举每一位就行了,分只有1位,有2位和3位讨论。。代码懒得写了。。

D:构造一个无向图使每个点度数为k且至少存在1座桥。。
我把1给特判了,考虑大于1的时候,桥的两侧单独考虑,若其中一侧有x个点,则这x个点的诱导子图的总度数为 xk1 所以k必为奇数,偶数无解。所以其实只要构造一侧,另一侧复制即可。我的做法是每侧 k+2 个点,其实画画图就构造的出来了,选出一个点作为连接口(不妨为 k+2 ),那么它只需要 k1 的度,让 1k1 号点向它连边, k k+1号点还需要 k 个度,但是不能向k+2连边,所以要向除 k+2 之外的所有点连边。做到这里 1k1 号点都有3个度了,还需要 k3 个,它们互相之间还未连边,若建成完全图那每个点会多出1个度,所以把它们两两配对,并去掉配对点之间的边,这样一侧就构造完了,另一侧同理。。WA了好几次,不清醒。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<cstring>
#define inf 0x3fffffff
using namespace std;
int k,n,m,i,j;
int main()
{
    scanf("%d",&k);
    if (k%2==0){printf("NO\n");return 0;}
    if (k==1)
    {
        printf("YES\n2 1\n1 2");
        return 0;
    }
    printf("YES\n%d %d\n",2*k+4,k*(k+2));
    int t=k+2;
    for (i=1;i<k;i++) printf("%d %d\n%d %d\n",i,k+2,i+t,k+2+t);
    for (i=1;i<k;i++) printf("%d %d\n%d %d\n",k,i,k+t,i+t);
    for (i=1;i<k;i++) printf("%d %d\n%d %d\n",k+1,i,k+t+1,i+t);
    printf("%d %d\n%d %d\n",k,k+1,k+t,k+t+1);
    for (i=1;i<k;i++)
        for (j=i+1;j<=k-1;j++)
            if (i+j!=k)printf("%d %d\n%d %d\n",i,j,i+t,j+t);
    printf("%d %d\n",k+2,k+2+t);
}

E:最后十几分钟才开始看,马上有了思路,但是有一种特殊情况没处理到,WA掉了。。把输入按最后连续的0的数量分类,如果最后是1,显然无解,最后有奇数个0,原封不动输出就行了,偶数个如果有超过2个0,把倒数2,3个0括起来就行了。如果有2个0的话,我直接输了无解,其实大部分情况是有解的,如果除了这两个0没有0了,那么是无解,否则我们可以把倒数第二个0和前面连续的一段1括起来,这样这一段可以看做就是一个0,那么最后两个0可以和往前一段连续的0并起来考虑,然后就同上了。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<cstring>
#define inf 0x3fffffff
#define N 100005
using namespace std;
int n,i,last,l2,l3,a[N];
int main()
{
    scanf("%d",&n);
    for (i=1;i<=n;i++)  scanf("%d",&a[i]);  
    last=1;l2=0;
    for (i=n;i;i--) if (a[i]) {last=i+1;break;}
    for (i=last-1;i;i--) if (!a[i]) {l2=i;break;}
    int cnt=n-last+1;
    if (a[n]==1||(cnt==2&&l2==0)) {printf("NO\n");return 0;}
    cout<<"YES"<<endl;
    if (l2) for (i=l2;i;i--) if (!a[i]) l3=i;else break;
    int cnt2=cnt+l2-l3+1;
    if (cnt==2)
    {
        if (cnt2%2==1) 
        {
            for (i=1;i<=l2;i++) printf("%d->",a[i]);
            printf("(");
            for (i=l2+1;i<last;i++) printf("%d->",a[i]);
            printf("0)->0");
            return 0;
        }
        else
        {
            for (i=1;i<l2;i++) printf("%d->",a[i]);
            printf("(0->");
            printf("(");
            for (i=l2+1;i<last;i++) printf("%d->",a[i]);
            printf("0))->0");
            return 0;
        }
    }
    if (cnt%2==1)
    {
        for (i=1;i<n;i++) printf("%d->",a[i]);printf("%d",a[n]);
    }
    else
    {
        for (i=1;i<n-2;i++) printf("%d->",a[i]);
        printf("(%d->%d)->%d",a[n-2],a[n-1],a[n]);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值