Codeforces Round #713 (Div. 3)

A. Spy Detected!
题解:输出只出现一次的数。

#include<bits/stdc++.h>
using namespace std;
int a[110], mp[110];
int main()
{
    int t, n, i;scanf("%d", &t);
    while (t--){
        memset(mp, 0, sizeof(mp));
        scanf("%d", &n);
        for (i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            mp[a[i]]++;
        }
        for (i = 1; i <= n; i++){
            if (mp[a[i]] == 1){
                printf("%d\n", i);
                break;
            }
        }
    }
}

B. Almost Rectangle
题意:输出由四个‘ * ’组成的矩形。
题解:构造。已知的两个‘ * ’和未知的两个‘*'同行或同列或同一对角线。

#include<bits/stdc++.h>
using namespace std;
char mp[410][410];
int main()
{
    int t, n, i, j;scanf("%d", &t);
    while (t--){
        scanf("%d", &n);
        for (i = 0; i < n; i++)
            scanf("%s", mp[i]);
        int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
        for (i = 0; i < n; i++)
        for (j = 0; j < n; j++){
            if (mp[i][j] == '*'){
                if (x1 == -1 && y1 == -1) x1 = i, y1 = j;
                else if (x2 == -1 && y2 == -1) x2 = i, y2 = j;
            }
        }
        if (x1 == x2){//同行
            if (x1 == 0) mp[x1 + 1][y1] = mp[x2 + 1][y2] = '*';
            else mp[x1 - 1][y1] = mp[x2 - 1][y2] = '*';
        }
        else if (y1 == y2){//同列
            if (y1 == 0) mp[x1][y1 + 1] = mp[x2][y2 + 1] = '*';
            else mp[x1][y1 - 1] = mp[x2][y2 - 1] = '*';
        }
        else{//对角线
            mp[x1][y2] = mp[x2][y1] = '*';
        }
        for (i = 0; i < n; i++)
            printf("%s\n", mp[i]);
    }
}

C. A-B Palindrome
题意:将原字符串构造成由a个0和b个1组成的字符串。
题解:构造。首先考虑-1的情况:
1.ab都为奇数,一定有一位多出来。
2.原字符串不是回文串。
3.原字符串中01个数比ab多。
然后根据已有01补齐对应问号,再根据ab补齐剩余问号。

#include<bits/stdc++.h>
using namespace std;
char s[400010];
int main()
{
    int t, a, b, i;scanf("%d", &t);
    while (t--){
        scanf("%d%d%s", &a, &b, s);
        if (a % 2 && b % 2){//ab都为奇数
            printf("-1\n");
            continue;
        }
        int flag = 1, l = strlen(s);
        for (i = 0; i < l / 2; i++){//判断原字符串是否回文
            if (s[i] == '?' || s[l - i - 1] == '?') continue;//一位有'?'不需要判断
            if (s[i] != s[l - i - 1]) flag = 0;
        }
        if (!flag){
            printf("-1\n");
            continue;
        }
        int cnt0 = 0, cnt1 = 0;
        for (i = 0; i < l; i++){
            if (s[i] == '0') cnt0++;
            else if (s[i] == '1') cnt1++;
        }
        if (cnt0 > a || cnt1 > b){//判断字符串中01个数是否合法
            printf("-1\n");
            continue;
        }
        a -= cnt0, b -= cnt1;
        bool boo = 1;
        for (i = 0; i < l; i++){//根据已有01去单个问号
            if (s[i] == '0' && s[l - i - 1] == '?'){
                if (a) a--, s[l - i - 1] = '0';
                else{
                    boo = 0;
                    break;
                }
            }
            else if (s[i] == '1' && s[l - i - 1] == '?'){
                if (b) b--, s[l - i - 1] = '1';
                else{
                    boo = 0;
                    break;
                }
            }
        }
        if (!boo){
            printf("-1\n");
            continue;
        }
        for (i = 0; i < l; i++){//根据ab补齐剩余问号
            if (s[i] == '?'){
                if (i == l / 2){//补一位
                    if (a) a--, s[i] = '0';
                    else if (b) b--, s[i] = '1';
                    else{
                        boo = 0;
                        break;
                    }
                    continue;
                }
                //补两位
                if (a >= 2){
                    s[i] = s[l - i - 1] = '0';
                    a -= 2;
                }
                else if (b >= 2){
                    s[i] = s[l - i - 1] = '1';
                    b -= 2;
                }
                else{
                    boo = 0;
                    break;
                }
            }
        }
        if (!boo) printf("-1\n");
        else printf("%s\n", s);
    }
}

D. Corrupted Array
题意:给一个b数组,前n项和a数组中的每一项相同,第n+1项等于a数组前n项和,第n+2项等于x。求a数组。
题解:假设b数组升序,分两种情况。
1.第n+1项次大,x最大,判断b数组前n项和与b[n+1]是否相同。
2.第n+1项最大,x次大,在前n+1项中枚举x,判断b数组的前n+1项和 减x的值与b[n+2]是否相同。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int b[200010];
int main()
{
    int t, n, i;scanf("%d", &t);
    while (t--){
        scanf("%d", &n);
        for (i = 1; i <= n + 2; i++)
            scanf("%d", &b[i]);
        sort(b + 1, b + n + 3);
        ll sum = 0;
        for (i = 1; i <= n; i++)
            sum += b[i];
        if (sum == b[n + 1]){//第一种情况
            for (i = 1; i <= n; i++){
                if (i > 1) printf(" ");
                printf("%d", b[i]);
            }
            printf("\n");
        }
        else{
            sum += b[n + 1];//第二种情况
            int x = -1;
            for (i = 1; i <= n + 1; i++){
                if (sum - b[i] == b[n + 2]){
                    x = b[i];
                    break;
                }
            }
            if (x != -1){
                int p = 0, ok = 0;
                for (i = 1; i <= n + 1; i++){
                    if (!ok && b[i] == x){//等于x的那一项不能输出
                        ok = 1;
                        continue;
                    }
                    if (p) printf(" ");
                    printf("%d", b[i]);
                    p++;
                }
                printf("\n");
            }
            else printf("-1\n");
        }
    }
}

E. Permutation by Sum
题意:判断[l,r]的和与s是否相等。
题解:从最小的区间[1,2,…,r-l+1]开始,从后往前一位一位的增加,每位最多增加n-(r-l+1)

#include<bits/stdc++.h>
using namespace std;
int a[510], vis[510];//标记值
int main()
{
    int t;scanf("%d", &t);
    while (t--){
        int n, l, r, s;
        scanf("%d%d%d%d", &n, &l, &r, &s);
        int minn = (1 + r - l + 1) * (r - l + 1) / 2;//最小序列和
        if (minn > s) printf("-1\n");
        else{
            memset(vis, 0, sizeof(vis));
            memset(a, 0, sizeof(a));
            s -= minn;
            for (int i = l; i <= r; i++)
                a[i] = i - l + 1;
            for (int i = r; i >= l; i--){
                int add = n - (r - l + 1);//每个数能加的最大值
                if (s >= add){
                    a[i] += add, s -= add;
                    vis[a[i]] = 1;
                }
                else{
                    a[i] += s, s = 0;
                    vis[a[i]] = 1;
                }
            }
            if (s > 0){//s不能恰好分配完
                printf("-1\n");
                continue;
            }
            for (int i = 1; i <= n; i++){//位置
                if (!a[i]){
                    for (int j = 1; j <= n; j++){//区间外的数
                        if (!vis[j]){
                            a[i] = j;
                            vis[j] = 1;
                            break;
                        }
                    }
                }
                if (i > 1) printf(" ");
                printf("%d", a[i]);
            }
            printf("\n");
        }
    }
}

F. Education
题意:现有n个长度的a数组和n-1个长度的b数组,c为购买电脑的费用。ai表示每天获得的钱,bi表示晋升到ai+1需要花费的钱。问最少几天能买得起电脑。
题解:思维、枚举。如果钱足够,能晋升的话就选择晋升,因为能获得更多的钱。再枚举ai,比较购买电脑的天数和晋升的天数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[200010], b[200010];
int main()
{
    int t;scanf("%d", &t);
    while (t--){
        int n, c;scanf("%d%d", &n, &c);
        for (int i = 0; i < n; i++)
            scanf("%lld", &a[i]);
        for (int i = 0; i < n - 1; i++)
            scanf("%lld", &b[i]);
        ll minn = 1e18 + 10;
        ll newdays = 0, cur = 0, money = 0;//晋升天数,当前天数,当前的钱
        for (int i = 0; i < n; i++){
            minn = min(minn, cur + (c - money + a[i] - 1) / a[i]);//以当前薪资水平购买电脑的最少天数
            newdays = (b[i] - money + a[i] - 1) / a[i];
            cur += newdays + 1;//晋升还需要单独的一天
            money += newdays * a[i] - b[i];//晋升后剩余的钱
        }
        printf("%lld\n", minn);
    }
}

G. Short Task
题解:思维。dn=1 + n +… = c, 故n<c,n的范围在[1,1e7]。先按照埃氏筛的方式求出di,再记录di对应的最小的数,最后找到c对应的位置。

#include<bits/stdc++.h>
using namespace std;
int d[10000010], pos[10000010];
void init()
{
    for (int i = 1; i <= 1e7; i++)
        for (int j = i; j <= 1e7; j += i)
            d[j] += i;//数j的因子之和
    for (int i = 1; i <= 1e7; i++){
        if (d[i] <= 1e7)
            if (!pos[d[i]]) pos[d[i]] = i;//pos记录di的最小位置
    }
}
int main()
{
    init();
    int t;scanf("%d", &t);
    while (t--){
        int n;scanf("%d", &n);
        if (!pos[n]) printf("-1\n");
        else printf("%d\n", pos[n]);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值