2017.5.15 COCI2011/2012 Contest#5

A KRIŽALJKA

【分析】
这一题只要仔细看题目的话应该是简单的,也相信大家不是来看我怎么花式讲水题的,就直接贴代码了。

【代码】

#include <bits/stdc++.h>
using namespace std;
#define M 40
char a[M],b[M];
int n,m,f=1;
int pos1,pos2;
char mp[M][M];
int main(){
    scanf("%s",a+1);
    scanf("%s",b+1);
    n=strlen(a+1);
    m=strlen(b+1);
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)mp[i][j]='.';
    }
    for(int i=1;f&&i<=n;i++){
        for(int j=1;f&&j<=m;j++){
            if(a[i]==b[j]){
                f=0;
                pos1=j;
                pos2=i;
            }
        }
    }
    for(int i=1;i<=n;i++)mp[pos1][i]=a[i];
    for(int i=1;i<=m;i++)mp[i][pos2]=b[i];
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)printf("%c",mp[i][j]);
        puts("");
    }
    return 0;
}

B EKO

【分析】
考虑到答案存在单调性,所以就直接二分咯。
想要1A的话还是要注意算md的时候有可能爆int。

【代码】

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define M 1000005
int a[M];
int n,m;
int l,r;
int res;
bool chk(int h){
    ll hav=0;
    for(int i=1;i<=n;i++){
        if(a[i]<=h)continue;
        hav+=a[i]-h;
    }
    return hav>=m;
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        r=max(r,a[i]);
    }
    while(!(l>r)){
        int md=1ll*(l+r)/2;
        if(chk(md)){
            res=md;
            l=md+1;
        }else r=md-1;
    }
    printf("%d\n",res);
    return 0;
}

C DNA

【分析】
知道题可以考虑贪心和dp,但是,我并没有找出容易的贪心做法,那就换一个路子,dp。
我们定义dp[i][j]表示将1~i全部变成j需要的最小个数。
那么转移方程也就比较容易推出了。
但是比赛的时候没有将这题1A,原因是RE了…

【代码】

#include<bits/stdc++.h>
using namespace std;
#define M 1000005
int dp[2][M];//B 0;A 1 
bool mk[M];
char a[M];
int n;
int main(){
    scanf("%d",&n);
    scanf("%s",a+1);
    for(int i=1;i<=n;i++){
        bool f=(a[i]=='A');
        dp[f][i]=min(dp[f][i-1],dp[!f][i-1]+1);
        dp[!f][i]=min(dp[f][i]+1,dp[!f][i-1]+1);
    }
    printf("%d",dp[1][n]);
    return 0;
}

D RAZBIBRIGA

【分析】
花了半天时间看英文题似懂非懂。感谢小C的中文题意。
我们发现,想要组成这样一个首尾相连的矩形,唯一有用的只是一个单词的开头和结尾的字母。
既然有四个起点和终点,那么我们就枚举终态。
不过还要考虑到一些重复算的相同的部分。如何将他们去掉,就看大家各显神通了。

【代码】

#include <bits/stdc++.h>
using namespace std;
#define M 100005
#define ll long long
char a[M][15];
int n,m;
ll ans;
int cnt[28][28];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
    m=strlen(a[1]+1);
    for(int i=1;i<=n;i++){
        int x=a[i][1]-'A';
        int y=a[i][m]-'A';
        cnt[x][y]++;
    }
    for(int i=0;i<26;i++){
        for(int j=0;j<26;j++){
            for(int k=0;k<26;k++){
                for(int p=0;p<26;p++){
                    int you[28][28];
                    memset(you,0,sizeof(you));
                    ll now=cnt[i][j];
                    you[i][j]++;
                    now*=1ll*(cnt[j][k]-you[j][k]);
                    you[j][k]++;
                    now*=1ll*(cnt[p][k]-you[p][k]);
                    you[p][k]++;
                    now*=1ll*(cnt[i][p]-you[i][p]);
                    if(now<=0)continue;
                    ans+=now;
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

E BLOKOVI

【分析】
比赛的时候完全没什么想法。直接敲了30分。
比赛结束后听jiedai大神的思路,感觉智商又下线了。
啦啦啦,我又回来了!

以下是sonytoy大神的证明

**我们假设已知当前积木 i 质量

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值