2020-05-18 — 习题训练一题解

A.Phoenix and Balance

题意:给一组数2^1,2^2,……,2^n,然后平均分为两组,使其两组和的差绝对值最小

注意到2 ^ (n+1) = 2^0 + ... 2 ^n +1;

所以 a[n] = a[0] + .. a[n-1] + 2;

含a[n]的一方尽可能选小的就可

#include <iostream>
#include <cstdio>
using namespace std;
int n, a[32];
int q_pow(int n)
{
    int a = 2, res = 1;
    while(n)
    {
        if(n & 1) res *= a;
        a *= a;
        n >>= 1;
    }
    return res;
}
int t;
int main()
{
    cin >> t;
    a[1] = 2;
    for(int i = 2;i <= 30; ++ i) a[i] = 2 * a[i-1];
    while(t--)
    {
        int res = 0;
        cin >> n;
        res = a[n];
        int num = 1;
        for(int i = 1;i <= n; ++ i)
        {
            if(num == n/2){
                for(int j = i;j <= n-1; ++ j)
                res -= a[j];
                break;
            }
            else{
                res += a[i];
                num ++;
            }
        }
        cout << res << endl;
    }

//    a[n] = a[1] + ... a[n-1] - 1;
//    a[n] + a[1] + ... a[m]  = 
}

B.Phoenix and Beauty

题意:给出n个数,通过进行增加新的数字(数字必须在1-n之间)使得数列周期为k, 并输出长度, 若弄不了,输出-1

当 k < n个数中不同的数时,输出-1吧,return 0;

扫一遍数组,遇到数就把所有的数都输出一遍,不够k个数随便添个数,凑够k个数,周期就是k了,长度不会超给定的范围

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
int n, a[6666], k, t, b[6666];
int main()
{
    cin >> t;
    while(t--)
    {
        memset(b, 0, sizeof(0));
        cin >> n >> k;
        int cnt = 0;
        for(int i = 1;i <= n; ++ i)
        {
            cin >> a[i];
            int flag = 1;
            for(int j = 1;j <= cnt; ++ j) 
            if(b[j] == a[i]) flag = 0;
            if(flag)
            b[++cnt] = a[i];
        }    
        sort(b + 1, b + 1 + cnt);
        if(k < cnt){
            cout << "-1" << endl;
            continue;
        }
        cout << n * k << endl;
        for(int i = 1;i <= n; ++ i)
        {
            for(int j = 1;j <= cnt; ++ j) cout << b[j] << " ";
            int j = k - cnt;
            while(j)
            {
                cout << b[cnt] << " ";
                j --;
            }
        }
        cout << endl;
    }
}

C.Road To Zero

题意:有两个数x,y,其中一个数增1或减1的话,需要花费a元,如果两个数一起减1或加1的话,需要花费b元,询问xy都变为0时花费的最少钱

分情况讨论

#include <iostream>
using namespace std;
typedef long long LL;
LL t, x, y, a, b;
int main()
{
    cin >> t;
    while(t--)
    {
        cin >> x >> y >> a >> b;
        LL minn = min(x, y), maxn = max(x, y);
        LL sum = x + y;
        LL ans = sum * a <= (minn * b + (maxn - minn) * a) ? sum * a :(minn * b + (maxn - minn) * a);
        cout << ans << endl;
    }
}

D.Binary Period

题意:给出01组成的字符串,进行寻找新的数组,并且已知数组可以通过对新数组的某个位置的数进行删除得到,并且使其是循环数组,循环的部分长度最短,总长度不超过2n

只有一个数时,周期为1,有两种数时由于 max_lenth <= 2n 循环输出01即可,子序列一定有原字符串

/*00 
0101
110   1010
11110 10101010
00001 01010101
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[666];
int t;
int main()
{
    cin >> t;
    while(t--)
    {
        int num0 = 0, num1 = 0;
        memset(s, 0, sizeof(s));
        cin >> s;
        for(int i = 0;i < strlen(s); ++ i)
        if(s[i] == '0') num0 ++;
        else num1++;
        if(num0 == 0 || num1 == 0){
            cout << s << endl;
            continue;
        }
        for(int i = 1;i <= strlen(s); ++ i)
        {
            cout << "0" << "1";
        }
        cout << endl;
    }

E.Nastay and Rice

题目:一共五个数n,a,b,c,d,计算(a-b)~(a+b),是否可以通过乘以n和(c-d)~(c+d)有交集 

分情况讨论就可

#include <iostream>
#include <cmath>
using namespace std;
int t, n, a, b, c, d;
int main()
{
    cin >> t;
    while(t--)
    {
        cin >> n;
        cin >> a >> b >> c >> d;
        int s = abs(a-b), e = a + b;
        if(s * n > c + d || e * n < abs(c-d)) cout << "NO" << endl;
        else cout << "YES" << endl; 
    }

}

F.Nastay and Door

题意:给你n,k,n个山峰值,山峰巅峰值就是这座山峰值比其他的都高,问在k个相连续的山峰中,山峰巅峰值个数是多少,并且这k个连续山峰中最左边的山峰坐标是多少

a[n] = 1, 2, 3 , 2, 4, 3
b[n] = 0, 0, 1, 1, 2, 2;
b[i-1] - b[i-k+1] 表示从i-k+1 到 i 中峰的个数
if(res < b[i-1] - b[i-k+1]) 就更新 res 和“答案”下标
#include <iostream>
using namespace std;
const int N = 2e5 + 10;
int t, n, k, a[N], b[N];
int main()
{
    cin >> t;
    while(t--)
    {
        cin >> n >> k;
        for(int i = 1;i <= n; ++ i) cin >> a[i];
        int res = 0, flag = 1;
        for(int i = 2;i <= n; ++ i)
        {
            if(i != n && a[i] > a[i+1] && a[i] > a[i-1])
            b[i] = b[i-1] + 1;
            else b[i] = b[i-1];
            
            if(i >= k && b[i-1] - b[i-k+1] > res)
            res = b[i-1] - b[i-k+1], flag = i-k+1;
        }
        cout << res + 1 << " " << flag << endl;
    }
}

 https://vjudge.net/contest/374474#overview

原文地址:https://www.cnblogs.com/DefineWaAc/p/12923800.html