• 校内集训(20170903)


    T1:卡片(card)

    【题目描述】

    lrb喜欢玩卡牌。他手上现在有张牌,每张牌的颜色为红绿蓝中的一种。现在他有两种操作。一是可以将两张任意位置的不同色的牌换成一张第三种颜色的牌;二是可以将任意位置的两张相同颜色的牌换成一张该颜色的牌。两个操作后都可以将生成的牌放到任意位置。现在他想知道,最后一张牌可能是什么颜色的。

    【输入描述】

    第一行输入一个,表示卡牌数量。

    第二行输入一个由’B’,’G’,’R’组成的长度为的字符串,分别表示卡牌的颜色为蓝色、绿色、红色中的一种。

    【输出描述】

    输出’B’,’G’,’R’中的若干个字母,按字典序输出。代表可能的最后一张牌的颜色。

    【样例】

    输入1

    输出1

    2

    RB

    G

    输入2

    输出2

    3

    GRG

    BR

    输入3

    输出3

    4

    BBBB

    B

    【数据范围】

    对于100%的数据,n<=200

    ——————————————————我是分割线————————————————————

    这是一道简单分析题。(入门难度。。不要吐槽)

    很显然我们发现如果3张牌都超过一张,三种情况都会出现(BGR)

    那么如果有2张牌都超过2张,同上

    剩下3种情况:

    1,1,0(数字表示牌的数量)那么答案就是牌数是0的那张

    2,1,0(2表示2张以上)那么答案就是牌数为1和0的两张

    1,0,0(1表示一张以上)那么答案就是牌数为1的那一张

    然后。。。做完了

    下面贴上代码

    #include<cstdio>
    using namespace std;
    int a[4],n;
    int er,yi,sa;
    char ch;
    char ans[3]={'B','G','R'};
    void swap(int &a,int &b){a^=b;b^=a;a^=b;}
    int main(){
        freopen("card.in","r",stdin);
        freopen("card.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            ch=getchar();
            while(ch<'A'||ch>'Z')ch=getchar();
            if(ch=='B')a[1]++;
            else if(ch=='G')a[2]++;
            else if(ch=='R')a[3]++;
        }
        for(int i=1;i<=3;i++)if(a[i]>=2)er++;
        for(int i=1;i<=3;i++)if(a[i]>=1)yi++;    
        if(er>=2||yi==3)puts("BGR");
        else if(er==1&&yi==2){
            int x,y;
            for(int i=1;i<=3;i++)if(a[i]==0)x=i;else if(a[i]==1)y=i;
            if(x>y)swap(x,y);
            printf("%c%c
    ",ans[x-1],ans[y-1]);
        }else if(yi==2){
            int x;
            for(int i=1;i<=3;i++)if(!a[i])x=i;
            printf("%c
    ",ans[x-1]);
        }else if(yi==1){
            int x;
            for(int i=1;i<=3;i++)if(a[i])x=i;
            printf("%c
    ",ans[x-1]);
        }
        fclose(stdin);
        fclose(stdout);
    }

    ————————————————我是分割线——————————————————

    T2:取数(win)

    【题目描述】

    lrb目前有个数字,他想知道这个数中选出若干个数,平均数减中位数的最大值是多少。可以证明,对于一个递增数列,如果是平均数减中位数最大时的中位数,表示在两边分别取相邻数字的数量,表示以为中位数,在两侧各取相邻个数时平均数减中位数的值,那么为关于的单峰函数。

    【输入描述】

    第一行为,为数字个数。

    第二行有个数,分别代表个数字。

    【输出描述】

    输出一个数,为平均数减中位数的最大值,保留两位小数。

    【样例】

    输入

    输出

    4

    1 2 3 4

    0.33

    【数据范围】

    对于60%的数据,n<=21

    对于75%的数据,n<=1000

    对于100%的数据,n<=10^5,0<=ai<=10^6

    ——————————————————我是分割线————————————————————

    这题首先我们要想到的就是枚举中位数。

    那么假设我们已知某一个数是中位数,那么我们怎么求最优的答案呢?

    对于一个已经排序过的数列,

    显然我们要在这个中位数的左边和右边同时取相同数量的数。

    对于中位数的左边,显然越靠近中位数的数越优,

    对于中位数的右边,越远离中位数的数越优。

    所以对于第i个数作为中位数的情况,我们左边从第i-1位开始向左取数,右边从第n位开始向左取数。而取数的个数自然就是三分啦!(三分的过程用前缀和O(1)求平均数)

    至于为什么偶数个数的数列不是最优解,这个我留个坑以后来填。

    下面贴代码(当然我写了偶数版本)

    #include<cstdio>
    #include<algorithm>
    #define MN 100005
    using namespace std;
    int a[MN],n;
    long long sum[MN];
    double ans=-100000000;
    int main(){
        freopen("win.in","r",stdin);
        freopen("win.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        int l=0,r=0,lm=0,rm=0,le=0;
        double la=a[1],ra=a[1];
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
        for(int i=1;i<=n;i++){
            le=min(i-1,n-i);
            le=max(le,0);
            l=0,r=le;
            while(l<r-1){
                lm=l+(r-l)/3,rm=r-(r-l)/3;
                la=(double)(sum[i-1]-sum[i-1-lm]+sum[n]-sum[n-lm]+a[i])/(double)(2*lm+1);
                ra=(double)(sum[i-1]-sum[i-1-rm]+sum[n]-sum[n-rm]+a[i])/(double)(2*rm+1);
                if(la<ra)l=lm+1;
                else r=rm-1;
            }
            la=(double)(sum[i-1]-sum[i-1-l]+sum[n]-sum[n-l]+a[i])/(double)(2*l+1);
            ra=(double)(sum[i-1]-sum[i-1-r]+sum[n]-sum[n-r]+a[i])/(double)(2*r+1);
            if(la<ra)ans=max(ans,ra-(double)a[i]);
            else ans=max(ans,la-(double)a[i]);
        }
        la=ra=(double)(a[1]+a[2])/2.0;
        for(int i=1;i<n;i++){
            le=min(i-1,n-i-1);
            le=max(le,0);
            l=0,r=le;
            while(l<r-1){
                lm=l+(r-l)/3,rm=r-(r-l)/3;
                la=(double)(sum[i-1]-sum[i-1-lm]+sum[n]-sum[n-lm]+a[i]+a[i+1])/(double)(2*lm+2);
                ra=(double)(sum[i-1]-sum[i-1-rm]+sum[n]-sum[n-rm]+a[i]+a[i+1])/(double)(2*rm+2);
                if(la<ra)l=lm+1;
                else r=rm-1;
            }
            la=(double)(sum[i-1]-sum[i-1-l]+sum[n]-sum[n-l]+a[i]+a[i+1])/(double)(2*l+2);
            ra=(double)(sum[i-1]-sum[i-1-r]+sum[n]-sum[n-r]+a[i]+a[i+1])/(double)(2*r+2);
            if(la<ra)ans=max(ans,ra-(double)((double)(a[i]+a[i+1])/(double)2));
            else ans=max(ans,la-(double)((double)(a[i]+a[i+1])/(double)2));
        }
        printf("%.2lf
    ",ans);
        fclose(stdin);
        fclose(stdout);
    }

     ————————————————我是分割线————————————————

    T3:密码(key)

    【题目描述】

    lrb去柜员机取钱,并输入了他的四位密码。但是这一切都被一个黑帮拍摄了下来。幸好,这一次他的银行卡里并没有剩余任何钱。lrb知道了他的账户被异常登录后十分害怕,然后修改了他的密码。从此以后他为了不被看出密码,他开始“徐晃”。但这一切还是被拍摄了下来,拍摄多次以后,这个黑帮找到了你,希望你在一秒内帮他算出lrb的可能使用的密码数量。

    【输入描述】

    第一行输入一个,为lrb被拍摄的动作次数。

    接下来行,每行第一个数为,表示lrb接下来的手指移动次数,接下来为一个长度为的数字串,表示lrb手指经过的轨迹。lrb手指经过的位置,可能没有按,也有可能按了多次。

    【输出描述】

    输出一行,为可能的密码数量。

    【样例】

    输入

    输出

    2

    3 123

    3 234

    5

    解释

    lrb可能用的是2222,2223,2233,2333,3333五种密码

    【数据范围】

    设所有轨迹串的总长度为。

    对于35%的数据,L<5000

    对于100%的数据,1<=n<=1000,1<=t<=10^4,L<=10^6

    ——————————————————我是分割线——————————————————

    这道题有一个简单思路(想不到的都是脑子抽了,比如我)

    我们只要枚举所有的密码就好了

    然后就是如何在O(n)时间内check一个密码

    我们只要开一个数组记录从每一位开始,后面的第一个0-9分别在第几位,如果都能够找到,那么密码合法。

    下面贴代码

    #include<cstdio>
    #define MN 1005
    #define M 1000005
    #define F(x,l,r) for(int x=l;x<=r;x++)
    using namespace std;
    char e[M];int f[M][10],ans,n,t[MN];
    int main(){
        freopen("key.in","r",stdin);
        freopen("key.out","w",stdout);
        scanf("%d",&n); 
        for(int i=1;i<=n;i++)scanf("%d%s",&t[i],e+t[i-1]),t[i]+=t[i-1];
        for(int i=0;i<=9;i++)f[t[n]][i]=t[n];
        for(int i=t[n]-1;i>=0;i--){for(int j=0;j<=9;j++)f[i][j]=f[i+1][j];f[i][e[i]-'0']=i;}
        F(a,0,9)
            F(b,0,9)
                F(c,0,9)
                    F(d,0,9){
                        int tot=0;
                        F(i,0,n-1)if(f[f[f[f[t[i]][a]][b]][c]][d]<t[i+1])tot++;
                        ans+=tot==n;
                    }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    MySQL--mysqldump的权限说明
    JS--switch 语句
    psutil官方文档
    mysql 性能分析套件
    mysql 在启动时配置文件的查找方式
    mysql中的意向锁IS,IX
    mysql innodb_double_write特性
    mysql sql_mode 之 NO_ENGINE_SUBSTITUTION
    编译安装hph
    pip list 和 pip freeze
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/7473367.html
Copyright © 2020-2023  润新知