2021-03-01

A [报数]

原题链接
一直计数,从1数到3,大于三就回到一,大于总人数就回到1,等于三的时候对应的人赋值为-1,遇到等于-1的人跳过,当等于-1的人是总人数减1时退出并输出对应的人的序号,注意几个if之间的顺序即可

#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 1000
int a[MAX];
int main()
{
    int n, pass = 0, num = 1, flag = 0;
    cin >> n;
    while (1) {
        if (num > 3) num = 1;
        pass++;
        if (pass > n) pass = 1;
        if (a[pass] == -1) continue;
        if (flag == n - 1) break;
        if (num == 3) {a[pass] = -1; flag++; }
        num++;
    }
    cout << pass;
    return 0;
}

B [拦截导弹(nlogn写法)]

原题链接
nlogn的求最大序列,思路为尽可能满足,先将第一个放进答案数组,若是下一个小于等于答案数组末尾,则数组长度加一,把现在这个数放进末尾,如果大于,则在答案数组中用stl函数找到第一个小于等于该数的数的位置,然后将这个数替换掉,需注意,答案数组中保存的并不是最长序列,只有长度为序列长度,因为思路为尽可能,答案数组重要的仅仅是有序最后一个数

greater()为内置的比较函数,大概就实现跟原本函数相反的功能(?)

#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 100005
int d[MAX], p[MAX], a[MAX];
int main()
{
    int h, len = 0;
    while (cin >> h) {
        a[++len] = h;
    }
    int len1 = 1, len2 = 1;
    d[1] = a[1];
    p[1] = a[1];
    for (int i = 2; i <= len; i++) {
        if(d[len1] >= a[i]) d[++len1] = a[i];
        else {
            int L1 = upper_bound(d + 1, d + 1 + len1, a[i], greater<int>()) - d;
            d[L1] = a[i];
        }
        if(p[len2] < a[i]) p[++len2] = a[i];
        else {
            int L2 = lower_bound(p + 1, p + 1 + len2, a[i]) - p;
            p[L2] = a[i];
        }
    }
    cout << len1 << endl << len2;
    return 0;
}

C [回文字符串]

原题链接
求加几个字母可以形成回文串
只需把原字符串倒过来求最长公共子序列的长度然后总长度减即可。。不能用string。。会莫名其妙报错

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
#define MAX 1005
int dp[MAX][MAX];
char a[MAX], b[MAX];
int main()
{
    int t;
    cin >> t;
    string x;
    while (t--) {
        cin >> x;
        int len = x.length();
        for (int i = 0; i <= len; i++) {
            dp[i][0] = dp[0][i] = 0;
        }
        for (int i = len - 1; i >= 0; i--) {
            a[i] = x[len - 1 - i];
            b[i] = x[i];
        }
        for (int i = 1; i <= len; i++) {
            for (int j = 1; j <= len; j++) {
                if (a[i - 1] == b[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        cout << (len - dp[len][len]) << endl;
    }
    return 0;
}

D [完美k倍子数组]

原题链接
在原数组中找一个序列,使得这个序列任意两个数的和都是输入数的倍数
1.若输入数时奇数,则该序列中每个数都必须是这个数的倍数才能满足,在输入时判断即可
2.若输入数是偶数,除了满足上一种条件可行之外,另一种是,这个数余输入数的值是输入数的一半,即a[i] % k = k / 2,这样才能满足两两相加为倍数
3.如果上面两种都不满足,则数组长度最大为2,判断条件为两个数与k的余数相加等于k,可以将余数存进set,然后用set快速查找

///https://nanti.jisuanke.com/t/T1271
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
#define MAX 100005
long long a[MAX];

bool find(long long A[], int n, long long k)
{
    set<long long> aa;
    for (int i = 0; i < n; i++) {
        long long a1 = a[i] % k;
        long long a2 = k - a1;
        if (aa.find(a2) != aa.end()) {
            return true;
        }
        aa.insert(a1);
    }
    return false;
}

int main()
{
    long long n, k, flag1 = 0, flag2 = 0;
    cin >> n>> k;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        if (!(a[i] % k)) flag1++;
        if (!(k % 2)) {
            if ((a[i] % k) == (k / 2)) flag2++;
        }
    }
    //大于1
    if (flag1 > 1 || flag2 > 1) {cout << max(flag1, flag2) << endl; return 0;}
    if (find(a, n, k)) {
        cout << 2 << endl;
        return 0;
    }
    else cout << -1 << endl;
    return 0;
}

E [刷墙]

原题链接
给你每个单位墙壁的高度,你可以使一个单位增加2的高度,或使两个相邻高度的墙壁增加1的高度,问能否全部一样高
不断检视,前一个,看是否同为奇数或同为偶数,如果为同一种类,则消去这两个再继续判断

#include <iostream>
#include<algorithm>
using namespace std;
#define MAX 200005
int n, a[MAX], len;

int main() {
    int t;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> t;
        a[++len] = t;
        if (len >= 2 && (a[len - 1] - a[len]) % 2 == 0) len -= 2;
    }
    if (len < 2) cout << "YES";
    else cout << "NO";
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值