Codeforces Round #233 (Div. 1) <A>

CF 398A  A. Cards

题目链接:

http://codeforces.com/problemset/problem/398/A

题目意思:

有a个‘o',b个’x',连续相同的字母组成一个块,如果块'o'的个数为x,则分数加上x^2,如果块‘x'的个数为y,则分数减去y^2。开始分数为0,求怎样分块使最终的分数最大。

解题思路:

枚举+贪心。

分析知,要把x的块的长度尽量的安排均匀,o的块尽量在一起。但如果把所有的o都安排在一起的话,也不一定是最优的,可以拿一个出来,把x再多分一份。所以可以枚举o分得1个的个数(i-1),其余的o是连续的,一共把x分成(i+1)份,使这(i+1)份尽可能均匀。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

ll a,b;
ll ans;

int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   while(~scanf("%I64d%I64d",&a,&b))
   {

       if(!a||b<=1) //直接输出
       {
           printf("%I64d\n",a*a-b*b);
           for(int i=1;i<=a;i++)
                printf("o");
           for(int i=1;i<=b;i++)
                printf("x");
           putchar('\n');
           continue;
       }

       ll ans=(ll)(-1e18); //初始化一个最小值
       //printf(":%I64d\n",ans);
       ll re1=0;

       for(int i=1;i<=a;i++) //分成i-1个1和1个(n-(i-1))两部分
       {
           if(i>=b) //总分数已大于b了
                break;

           ll temp=b/(i+1); //每份的个数
           ll mo=b%(i+1);  //多余的 在分给前mo份

           ll cur=(a-(i-1))*(a-i+1)+(i-1)-mo*(temp+1)*(temp+1)-temp*temp*(i+1-mo);
           //temp+1的有mo个 temp有(i+1-mo)个

           if(cur>ans) //更新结果
           {
               ans=cur;
               re1=i;
           }
       }
       printf("%I64d\n",ans);

       ll temp=b/(re1+1); //每份的个数
       ll mo=b%(re1+1);  //多余的 再给前mo份一份加一个

       for(int i=1;i<=temp;i++)
            printf("x");
       if(mo)
       {
           printf("x");
           mo--;
       }
       for(int i=2;i<=re1+1;i++)
       {
           if(i==2)
           {
               for(int j=1;j<=(a-(re1-1));j++) //先输出(n-(i-1))
                    printf("o");
           }
           else
                printf("o");
           for(int j=1;j<=temp;j++)
                printf("x");
           if(mo)
           {
               printf("x");
               mo--;
           }
       }
       putchar('\n');





   }
   return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值