Codeforces Round 339 div2

Codeforces Round 339 div2
通过数:3
Standing: 325 / 5845
比赛状态不是很好,尤其是第一题大数被叉掉后整个人都不好了。第三题计算几何问可为借的版,后来老耿说海伦公式就可以过……
补第四题的时候自己写的,结果WA了两天,最后发现思路有问题详见代码。
第五题问的Q神,再次感谢~

A:
问[L,R]区间
套的大数版,就不粘贴代码因为太占篇幅。
有判断下一次做乘法是否会溢出的做法,说完秒懂感觉智商低……
B:
问一堆数的乘积是多少。这些数比较特殊,最多只有一个“非法数”,其余都是合法数:十进制表示最多有一位是1,其余均是0。
刚好那天在手残期,而且好像那个非法数用long long读取的时候会爆掉还是怎么样,瞎改成字符串就过了。这点我想投诉,明明说的输入integer好嘛!

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
#define LL long long
int valid(char *s)
{
    int t1 = 0;
    while(*s){
        int temp = *s - '0';
        if(temp > 1) return 1;
        if(temp == 1) t1++;
        s++;
    }
    if(t1 <= 1) return 0;
    else return 1;
}
char s[100000 + 4];
char t2[100000 + 4];
int main()
{
    int n;
    while(scanf("%d", &n) != EOF){
        int ok = 1;
        LL t1 = 0;
        strcpy(t2, "1");
        for(int i = 1 ; i <= n ; i++){
            LL u;  scanf("%s", s);
//            printf("i = %d\n", i);
            if(!strcmp(s, "0")) ok = 0;
            else if(!strcmp(s, "1")) continue;
            else{
                int flag = valid(s);
                if(flag){
                    strcpy(t2, s);
                }
                else{
                    for(int i = 0 ; i < (int)strlen(s) ; i++){
                        int u = s[i] - '0';
                        if(u == 0) t1++;
                    }
                }
            }
        }
        if(ok == 0) printf("0\n");
        else{
            printf("%s", t2);
            for(int i = 0 ; i < t1 ; i++) printf("0");
            printf("\n");
        }
    }
    return 0;
}

C:
问一堆点围成的凸包,绕一个点旋转一圈形成的圆环面积。
想了想无非是找最近和最远点。然而WA了,以为是精度问题继续WA了8发。
就在我以为这次要掉成渣的时候,突然发现最近点不是每个点每个点来求,比如两个点形成的线段上可能就有最近点。
然后到处找版,要了个点到线段的距离版过了。

int dcmp(double x) {
    if(fabs(x)<eps)  return 0;else return x < 0 ? -1 : 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x = _x;y = _y;
    }
};

bool operator < (const Point& a,const Point& b) {
    return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
bool operator == (const Point& a,const Point &b) {
    return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}

double dis(Point a,Point b){
    return  sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

typedef Point Vec;   //оРа©

Vec operator + (Vec A,Vec B)  {return Vec(A.x+B.x,A.y+B.y); }

Vec operator - (Point A,Point B)  {return Vec(A.x-B.x,A.y-B.y); }

Vec operator * (Vec A,double p)  {return Vec(A.x*p,A.y*p); }

Vec operator / (Vec A,double p)  {return Vec(A.x/p,A.y/p); }

double Dot (Vec A,Vec B)  { return A.x*B.x+A.y*B.y; }

double Length(Vec A)  { return sqrt(Dot(A,A)); }

double Angle(Vec A,Vec B)  { return acos(Dot(A,B)/Length(A)/Length(B)); }

double Cross(Vec A,Vec B)  { return A.x*B.y-A.y*B.x; }

double Dis_to_Seg(Point P,Point A,Point B){
    if(A==B)  return Length(P-A);
    Vec v1=B-A,v2=P-A,v3=P-B;
    if(dcmp(Dot(v1,v2))<0)  return Length(v2);
    else if(dcmp(Dot(v1,v3))>0)  return Length(v3);
    else return fabs(Cross(v1,v2))/Length(v1);
}

D:
一个数字序列,长度(1e5)。每个数字最大A,以后的操作中也只能把它最大变成A。
现在有一个函数g = cm * mmin + cf * numOfValueEqualToA。
现在可以对一个数加1加m次,问这个函数的最大值是多少。

显然扫描线,还有一种叫法叫two pointer吧,然而不断WA。后面开的随机数大法才找到问题,有一个小细节没处理到。还是太菜。

AC版:
/*
    主要错误是思路和逻辑的错误。当属于最低水平的一个数划归给最高水平时,最低水平有全部提升的可能。
    写法上试图开一个全局变量来维护,结果是分类讨论过多导致细节繁琐。更好的办法是尽可能的封装起每一个步骤,让每个模块之间只有输入输出互相接触。
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define LL long long
#define MAXN (200000+5)
struct D
{
    LL data;
    int mark;
}d[MAXN];
LL sum[MAXN];
bool cmp1(D a, D b){return a.data < b.data;}
bool cmp2(D a, D b){return a.mark < b.mark;}
int main()
{
    LL n, a, cf, cm, m;
    while(scanf("%I64d%I64d%I64d%I64d%I64d", &n, &a, &cf, &cm, &m) != EOF){
        for(int i = 1 ; i <= n ; i++){
            scanf("%I64d", &d[i].data);
            d[i].mark = i;
        }
        sort(d + 1, d + 1 + n, cmp1);
        for(int i = 1 ; i <= n ; i++){
            sum[i] = sum[i - 1] + d[i].data;
        }
        LL ans = 0;
        int t1, t2, t3;
        t1 = 0, t2 = n;
        int re = n;
        for(int i = n ; i >= 0 ; i--){
            LL cost2 = a * (n - i) - (sum[n] - sum[i]);
            LL cost1 = m - cost2;
            if(cost1 < 0) break;
            re = min(re, i);
            while(re && d[re].data * re - sum[re] > cost1) re--;
            LL data = (cost1 - d[re].data * re + sum[re]) / re + d[re].data;
            data = min(data, a);
            if(i == 0) data = a;
            LL tans = data * cm + cf * (n - i);
            if(ans < tans){
//                printf("tans = %I64d, data = %I64d\n", tans, tdata)
                ans = tans;
                t1 = re, t2 = i, t3 = data;
            }
        }
        for(int i = 1;  i <= t1 ; i++) d[i].data = t3;
        for(int i = t2 + 1 ; i <= n ; i++) d[i].data = a;
        sort(d + 1, d + 1 + n, cmp2);
        printf("%I64d\n", ans);
        for(int i = 1 ; i <= n ; i++){
            printf("%I64d", d[i].data);
            if(i == n) printf("\n");
            else    printf(" ");
        }
    }
    return 0;
}
WA版:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int MAXN = 100000 + 5;
struct D
{
    LL data;
    int mark;
}d[MAXN];
LL sum[MAXN];
bool cmp1(D a, D b){return a.data < b.data;}
bool cmp2(D a, D b){return a.mark < b.mark;}
int main()
{
//    freopen("data.txt", "r", stdin);
//    freopen("data1.txt", "w", stdout);
    LL a, n, cf, cm, m;
    while(scanf("%I64d%I64d%I64d%I64d%I64d", &n, &a, &cf, &cm, &m) != EOF){
        d[0].data = 0;
        for(int i = 1 ; i <= n ; i++) {
            scanf("%I64d", &d[i].data); d[i].mark = i;
        }
        sort(d + 1, d + n + 1, cmp1);
        for(int i = 1 ; i <= n ; i++) sum[i] = sum[i - 1] + d[i].data;
//        d[0].data = d[1].data;
        LL now = 1;
        LL data = d[1].data;
        LL cost1 = 0;
        while(now < n && cost1 <= m){
            if((d[now + 1].data - data) * now + cost1 > m){
                LL tdata = (m - cost1) / now + data;
                cost1 = cost1 + (tdata - data) * now;
                data = tdata;
                break;
            }
            else{
                cost1 += (d[now + 1].data - data) * now;
                data = d[++now].data;
            }
//            if(sum[now] < m)
        }

        if(now == n && cost1 <= m){
            LL tdata = min(a, (m - cost1) / now + data);
            cost1 = cost1 + (tdata - data) * now;
            data = tdata;
        }
        LL ans = cm * data;
        if(data == a) ans += cf * n;
        else{
            LL temp = n;
            while(temp >= 1 && d[temp].data == a) ans += cf, temp--;
        }
        LL t1, t2, t3;
        t1 = now, t2 = n + 1, t3 = data;
//        printf("now = %d, data = %I64d, ans = %I64d\n", now, data, ans);
        LL cost2 = 0;
        for(LL i = n ; i >= 1 ; i--){
            cost2 += (a - d[i].data);
            if(cost2 > m) break;
//            if(i == 81) printf("cost1 = %I64d, cost2 = %I64d, m = %I64d\n", cost1, cost2, m);
            while(now >= i || cost1 + cost2 > m){
                if(now == 0) break;
                while(d[now].data == data && now >= 1) now--;
//                if(cost1 + cost2 <= m){
//                    if(i == 1982) printf("first\n");
//                    if(i == 1982){
//                        printf("cost1 = %I64d, data = %I64d, d[now].data = %I64d\n", cost1, data, d[now].data);
//                    }
//                    cost1 -= (data - d[now].data) * now; data = d[now--].data;
//                }
//                else{
//                    if(i == 1982) printf("second\n");
                    LL temp = (data - d[now].data) * now;
//                    printf("temp = %I64d\n", temp);
                    if(cost1 + cost2 - temp > m){cost1 -= temp, data = d[now--].data;}
                    else if(cost1 + cost2 <= m)
                    else{
//                        printf("second\n");
                        LL tdata = data - ceil(1.0 * (cost1 + cost2 - m) / now);
                        if(tdata >= data) tdata = data - 1;
//                        printf("tdata = %I64d, cost1 + cost2 - m = %I64d, now = %I64d\n", tdata, cost1 + cost2 - m, now);
//                        printf("data = %I64d, tdata1 = %I64d, ", data, tdata);
                        tdata = max(tdata, d[now].data);
//                        printf("tdata2 = %I64d\n", tdata);
                        cost1 -= (data - tdata) * now;
                        data = tdata;
//                    }
                }
//                else{
//                    LL temp = (data - d[now].data) * now;
//                    if(cost1 + cost2 - temp >= m) cost1 -= temp, data = d[now--].data;
//                    else{
//                        LL tdata = data - floor(1.0 * (cost1 + cost2 - m) / now);
////                        tdata = max(tdata, d[now].data);
//                        cost1 = cost1 - (data - tdata) * now;
//                        data = tdata;
//                        if(tdata == d[now].data) now--;
//                    }
//                }
//                printf("now = %I64d, cost1 = %I64d, cost2 = %I64d, m = %I64d, data = %I64d, i = %I64d\n", now, cost1, cost2, m, data, i);
//                system("pause");
            }
//                printf("i = %I64d, data = %I64d, cost1 = %I64d, cost2 = %I64d, now = %d\n", i, data, cost1, cost2, now);
//            if(n == 2054 && data == 5674) printf("i = %d\n", i);
//            printf("i = %d, data = %I64d\n", i, data);
            if(cost1 + cost2 > m) break;
            if(i == 1) data = a;
            LL tans = cm * data + cf * (LL)(n - i + 1);
            if(ans < tans){
                ans = tans;
                t1 = now, t2 = i, t3 = now <= 0 ? a : data;
            }
        }
        for(int i = 1 ; i <= t1 ; i++) d[i].data = t3;
        for(int i = t2 ; i <= n ; i++) d[i].data = a;
        sort(d + 1 , d + 1 + n, cmp2);
        printf("%I64d\n", ans);
        for(int i = 1 ; i <= n ; i++){
            printf("%I64d", d[i].data);
            if(i == n) printf("\n");
            else    printf(" ");
        }
    }
}

E:
参考了TankEnginer大神代码,听了q神思路。
26个字母分别有多少多少个。保证所有字母的个数和<=1e6.
然后问这样一种把他们排列的组合,使得他们构成一个环。这个环上从两个字母间分开后能得到一个回文串,然后这种分开的地方最多……好绕,文字功力有限。
分类讨论。首先把最简单的只有一种字母的情况去掉。然后发现字母数量为奇数个时对答案有影响所以分开讨论。两个以上无解。一个和0个分开讨论。这时可以把这个环看成几个几个的小等分,小等分们或对称(0个),或相同(1个)。小等分的长度是所有字母数量的最大公约数。然后不断不断的reverse,或者equalto。
然后你看看代码?

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define gcd(a,b) __gcd(a,b)
const int MAXN = 1e6 + 5;
int num[50];
char str[MAXN];
int main()
{
    int n;
    while(scanf("%d", &n) != EOF){
        int ok = 2;
        int mmin = MAXN, re;
        int sum = 0;
        for(int i = 0 ; i < n ; i++){
            scanf("%d", &num[i]);
            sum += num[i];
            if(num[i] % 2 == 1) ok--, re = i;
            if(mmin > num[i]) mmin = num[i];
        }
        int ans = 0;
        if(n == 1){
//            printf("%d\n", sum);
            ans = num[0];
            for(int i = 0 ; i < num[0] ; i++) str[i] = 'a';
            str[num[0]] = '\0';
        }
        else if(ok <= 0){
            ans = 0;
            int now = 0;
            for(int i = 0 ; i < n ; i++) for(int j = 0 ; j < num[i] ; j++) str[now++] = 'a' + i;
            str[now] = '\0';
        }
        else if(ok == 1){
//            printf("first\n");
            int g = 0;
            for(int i = 0 ; i < n ; i++){
                if(num[i] % 2 == 0){
                    g = g == 0 ? num[i] : gcd(g, num[i]);
                }
            }
            g /= 2;
            g = gcd(g, num[re]);
            ans = g;

            int now = 0;
            for(int i = 0 ; i < g ; i++){
                for(int j = 0 ; j < num[re] / g ; j++) str[now++] = re + 'a';
                for(int j = 0 ; j < n ; j++){
                    if(j == re) continue;
                    for(int k = 0 ; k < num[j] / g / 2 ; k++)
                        str[now++] = j + 'a';
                }
                for(int j = n - 1 ; j >= 0 ; j--){
                    if(j == re) continue;
                    for(int k = 0 ; k < num[j] / g / 2 ; k++)
                        str[now++] = j + 'a';
                }
            }
            str[now] = '\0';
        }
        else{
            int g = 0;
            for(int i = 0 ; i < n ; i++)
                g = g == 0 ? num[i] : gcd(g, num[i]);
            ans = g;

            int now = 0;
            for(int i = 0 ; i < n ; i++){
                for(int j = 0 ; j < num[i] / g ; j++)
                    str[now++] = 'a' + i;
            }
            int p = now;
            for(int temp = 0 ; temp < g - 1 ; temp++){
                int cur = now;
                for(int i = 0 ; i < n ; i++){
                    for(int j = 0 ; j < num[i] / g ; j++){
//                        printf("now = %d, cur * 2 - 1 - now = %d, cur = %d\n", now, cur * 2 - 1 - now, cur);
                        str[now] = str[cur * 2 - 1 - now];
                        now++;
                    }
                }
            }
//            for(int temp = 0 ; temp < g - 1 ; temp++){
//                int cur = now;
//                for(int j = 0 ; j < p ; j++)
//                    str[now++] = str[cur - 1 - j];
//            }
            str[sum] = '\0';
        }
        printf("%d\n", ans);
        puts(str);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值