天天看点

CodeForces 398A Cards

题意:

a个o  b个x  排在一条线上  排列的得分计算方法是  连续y个o就+y^2  连续y个x就-y^2  问  最大得分和排列方式

思路:

直接想到xxooooox这种排列的方式  然后交  然后WA - -b

看了下题解才意识到  增加o的份数虽然会影响+的分  但是可以缩小-的分 (我之前一直认为分开o不好…)

然后就是枚举o的份数即可  x的份数能比o多就多一份

为了+的尽量大  o的分布应该集中  所以就除了一组以外其他都是1

为了-的尽量小  x就应该平摊

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

__int64 a,b,val,ans,tmp;

int main()
{
    int i,j,ta,tb;
    scanf("%I64d%I64d",&a,&b);
    if(!a)
    {
        printf("%I64d\n",-b*b);
        while(b--) printf("x");
        printf("\n");
        return 0;
    }
    if(!b)
    {
        printf("%I64d\n",a*a);
        while(a--) printf("o");
        printf("\n");
        return 0;
    }
    val=a*a-b*b; ans=1;
    for(i=1;i<=a;i++)
    {
        if(b>=i+1) j=i+1;
        else break;
        tmp=( (a-i+1)*(a-i+1) + i-1 ) - ( (b/j+1)*(b/j+1)*(b%j) + (b/j)*(b/j)*(j-b%j) );
        //printf("%d %I64d\n",i,tmp);
        if(tmp>val)
        {
            val=tmp;
            ans=i;
        }
    }
    printf("%I64d\n",val);
    ta=ans-1;
    tb=b%(ans+1);
    for(i=1;i<=ans*2+1;i++)
    {
        if(i&1)
        {
            if(tb)
            {
                j=b/(ans+1)+1;
                tb--;
            }
            else j=b/(ans+1);
            while(j--) printf("x");
        }
        else
        {
            if(ta)
            {
                j=1;
                ta--;
            }
            else j=a-ans+1;
            while(j--) printf("o");
        }
    }
    printf("\n");
    return 0;
}