Educational Codeforces Round 68 (Rated for Div. 2) A B C D

题目链接:http://codeforces.com/contest/1194


Problem A

找规律,发现会一次去掉1,3,5,7直到剩余数字小于等于一半

于是奇数剩余:2,4,6,...n-1

        偶数剩余:2,4,6,....n

问你第几个数,只要*2就行了

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>

using namespace std;

#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pb push_back
#define fi first
#define se second
#define debug(x) printf("----Line %s----\n",#x)
#define pt(x,y) printf("%s = %d\n",#x,y)
#define INF 0x3f3f3f3f

const int N = 1e5+5;



int main()
{
    int T;scanf("%d",&T);while (T--){
        ll n,x;
        scanf("%I64d %I64d",&n,&x);
        printf("%I64d\n",x*2);
    }

    return 0;
}

Problem B

送命题,复杂度摸不透,比赛时候觉得暴力的话空间开不起,时间不够跑。

一行行遍历时用vector储存下所有最长的行上面的空白格的位置(因为可能不止一条最长的),这写空白的位置是为了等会选取

最长竖时是否存在可以共同填掉一格,当然也要记下‘*’最多的那一(几)行的‘*’数目

遍历的时候同时统计每一列的‘*’数目cnt[]。

当遍历完整个图的时候,我们把vector里面的空白格全部倒出来开一个bool数组标记每个空白格的位置

开始遍历cnt也就是每一列的‘*’数目,来求答案,如果当前列的空白格被标记过,说明如果我们要填充这一列,这个空白格可以

同时受用这一列和最长的一行,所以总共需要涂色的等于最大行和这一列所欠缺的。取最大值即可。。。。。。

等等,为什么这种复杂度都能过啊喂???!

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>

using namespace std;

#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pb push_back
#define fi first
#define se second
#define debug(x) printf("----Line %s----\n",#x)
#define pt(x,y) printf("%s = %d\n",#x,y)
#define INF 0x3f3f3f3f

const int N = 5e4+5;

vector<int>br;
int cnt[N];
bool kong[N];

int main()
{
    int T;scanf("%d",&T);while (T--){
        br.clear();
        memset(cnt,0,sizeof cnt);
        int n,m;
        int sum=-1,maxlen=-1,maxrow=-1;
        char c;
        scanf("%d %d",&n,&m);
        getchar();
        for1(i,1,n){
            sum = 0;
            vector<int>temp;
            for1(j,1,m){
                scanf("%c",&c);
                if (c=='.') temp.pb(j);
                else cnt[j]++,sum++;
            }
            getchar();
            if (sum>maxlen) br.clear(),br=temp,maxlen = sum;
            else if (sum==maxlen) br.insert(br.end(),temp.begin(),temp.end());
        }

//for (auto now:br) cout << now << " "; puts("");

        memset(kong,false,sizeof kong);

        for (auto now:br) kong[now] = true;

//for1(i,1,m)printf("%s",kong[i]?"kong ":"man ");puts("");

        int ans = n+m+1;

        for1(i,1,m){
            if (cnt[i]>=maxrow){
                if (kong[i]) ans = min(ans,n-cnt[i]+(m-maxlen)-1);
                else ans = min(ans,n-cnt[i]+(m-maxlen));
                maxrow = cnt[i];
            }
        }

        printf("%d\n",ans);

    }

    return 0;
}

Problem C

把第三个串拥有的字符统计出来相当于第一个串的后备隐藏能源,来和第二个串匹配,优先用串1自己的匹配串2,

最后成功的条件是串1用完,串2用完,否则不成功。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>

using namespace std;

#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pb push_back
#define fi first
#define se second
#define debug(x) printf("----Line %s----\n",#x)
#define pt(x,y) printf("%s = %d\n",#x,y)
#define INF 0x3f3f3f3f
#define idx(i) i-96

const int N = 1e5+5;

char s[110],t[110],p[110];
int cnt[30];


int main()
{
    int T;scanf("%d",&T);while (T--){
        scanf("%s %s %s",s,t,p);
        memset(cnt,0,sizeof cnt);
        for (int i=0;p[i];i++)
            cnt[idx(p[i])]++;

        int tot=0,i=0;
        int lens = strlen(s);
        int lent = strlen(t);

        for (i=0;i<lent;i++){
            if (t[i]==s[tot]) tot++;
            else if (cnt[idx(t[i])]>0) cnt[idx(t[i])]--;
            else break;
        }

        if (tot==lens && i>=lent) printf("Yes\n");
        else puts("No");

    }
    return 0;
}

Problem D

问题转换为:n个石头,每次可取1,2,k个,先取完就赢。

这道题只有一堆,跟sg函数看起来扯不到关系。

询问有很多次,每次k都不同,那么应该有什么共同的规律。

打个表找找规律。

k不是3的倍数时:

B AAB AAB AAB...

是三3倍数时:

k=3,B AAAB AAAB AAAB...

k=6,B AAB AAAB AAB AAAB ...

k=9,B AAB AAB AAAB AAB AAB AAAB...

k=12,B AAB AAB AAB AAAB AAB AAB AAB AAAB...

......

打表:(不是AC代码,那个在下面)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>

using namespace std;

#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pb push_back
#define fi first
#define se second
#define debug(x) printf("----Line %s----\n",#x)
#define pt(x,y) printf("%s = %d\n",#x,y)
#define INF 0x3f3f3f3f

const int N = 1e5+5;

char zt[N];

int main()
{
    //freopen("C:/Users/DELL/Desktop/input.txt", "r", stdin);
    //freopen("C:/Users/DELL/Desktop/output.txt", "w", stdout);
    int n,k;
    //int T;scanf("%d",&T);while (T--){}
    while (~scanf("%d %d",&n,&k)){/// P 表示先手必胜,N 表示先手必败
        zt[0] = 'N';
        zt[1] = 'P';
        zt[2] = 'P';
        zt[k] = 'P';
        for (int i=3;i<=n;i++)
            if (zt[i-1]=='N'||zt[i-2]=='N'||(i>=k && zt[i-k]=='N')) zt[i] = 'P';
            else zt[i] = 'N';

        printf("当k=%d时:\n",k);

        for0(i,0,n+1) printf("n = %d, %s\n",i,zt[i]=='P'?"Alice,first win":"Bob,second win");

    }
    return 0;
}

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>

using namespace std;

#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pb push_back
#define fi first
#define se second
#define debug(x) printf("----Line %s----\n",#x)
#define pt(x,y) printf("%s = %d\n",#x,y)
#define INF 0x3f3f3f3f

const int N = 1e5+5;

int a[N];

int main()
{
    int T;scanf("%d",&T);
    while (T--){
        int n,k;
        scanf("%d %d",&n,&k);

        if (n==0){printf("Bob\n");continue;}
        if (n==1||n==2){printf("Alice\n");continue;}

        if (k%3!=0){
            n = n%3;
            if (n==1||n==2) printf("Alice\n");
            else printf("Bob\n");
        }
        else {
            int x = k/3-1;
            int cycle = 3*x + 4;
            n = n%cycle;
            if (n==cycle-3||n==cycle-2||n==cycle-1) printf("Alice\n");
            else if (n==0) printf("Bob\n");
            else if (n%3==1||n%3==2) printf("Alice\n");
            else printf("Bob\n");
        }
    }
    return 0;
}

总结:

①AC了几千个人的题目一定没那么难,一定要想清楚,敢暴力

ps:vector可以直接容器间赋值,vector(v.begin,vv.begin,vv.end)可以直接实现对应位置的插入

②博弈论该去系统学一学了,sg,打表,各种变形。

③分已经真的没有掉的余地了,下一场让我多A几道,求你了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值