Codeforces Round 870 (Div. 2)

A. Trust Nobody

题意:有n个people,每个人会说一个数字,表示在这n个人里有至少几个人在说谎,这些人说的可能是真的,也可能是假的。请根据这些人提供的信息判断这n个人里面有几个人在说谎,如果不能判断(提供的信息矛盾)则输出-1。如果有多种可能,输出anyone of them

思路:首先先将数据整理为按说谎人数从低到高排序的形式。 假设有x个人说有y个人说谎,那么x+y的值必然不大于n,如果大于n,说明这几个人的发言是contradictory的,如果所有人的发言都是contradictory,那么就输出-1。接下来判断所有可能的答案:如果有x个人说有至少y个人说谎,那么如果刚好有y个人说谎,则x+y == n, 题目的关键点在于“至少”有y个人说谎,所以问题演变成,至少有x个人说谎递推后变为至少有x + i个人说谎(0 <= i <= n - x),也就是说当前问题的解析(x)是从上一步的(x)累加过来的。于是问题简化为三步:得出x与y的映射;得到前缀和数组;complete search得到解析。


#include <bits/stdc++.h>

using namespace std;

typedef vector<int> vi;
typedef long long int ll;
typedef vector<ll> vll;
typedef pair<int, int> pii;

#define lowbit(S) ((S)& -(S))



int main(){
 ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int N;
    cin >> N;
    while (N--){
        int n;
        cin >> n;
        vi a(120);
        int maxx = 0;
        for (int i = 0; i < n; ++i){
            int t;
            cin >> t;
            a[t] += 1;
            maxx = max(maxx, t);
        }
        int cnt = -1;
        for (int i = 1; i <= maxx; ++i) a[i] += a[i - 1];
        for (int i = 0; i <= maxx; ++i){
            if (a[i] + i == n) cnt = n - a[i];
        }
        cout << cnt << endl;
    }
    return 0;
}











总结:题目不晦涩好理解,但是一开始卡在contradictory上面,无法理解是什么情况导致的contradictory,然后多看了几个输入跟输出示例后才理解。所以读输入输出示例很重要,但是输入输出示例也会挖坑,比如题目中给出的测试示例全都是矛盾的人数=说谎的人数,直接产生了误导性,让人很容易忽略“at leatst"这个条件。数据的组织形式就是简单的手动hashmap,再加上题目的条件求个前缀和直接判定即可。难点就是很难短时间找到切入点以及深刻理解题意。这种题目需要多读题跟测试实例,迅速找到关键的点。

B. Lunatic Never Content

题意:给定一个数组,让这个数组mod一个数后是一个palindrome数组,问这个数最大能是多少,如果这个数无限大,输出0。

思路:数组mod x后是palindrome,那么首尾对应的位置modx后余数相等,知道两个数数值的情况下,可以很简单的通过减法运算来得到这个数x。于是,对于每一对数,为了保证最后mod x后数组为palindrome,需要对每一对数都求出一个x,然后找出一个最大的通用的x,让这个x可以满足所有的数对。于是问题转变成对于一堆数x,找出gcd的问题。显而易见,最差的情况下gcd得到1,另一种情况即字符串本来就是回文串,即x可以infinit...

上代码


#include <bits/stdc++.h>

using namespace std;

typedef vector<int> vi;
typedef long long int ll;
typedef vector<ll> vll;
typedef pair<int, int> pii;

#define lowbit(S) ((S)& -(S))


template<typename T>
T gcd(T a, T b){return b == 0 ? a : gcd(b, a % b);}


template<typename T>
T lcm(T a, T b){return a / gcd(a, b) * b;}


int main(){
 ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int N;
    cin >> N;
    while (N--){
        int n, result = 0x3f3f3f3f;
        cin >> n;
        vi a(n);
        for (auto& x : a) cin >> x;
        for (int i = 0; i < (n - i - 1); ++i){
            if (a[i] == a[n - i - 1]) continue;
            if (result == 0x3f3f3f3f) result = abs(a[i] - a[n - i - 1]);
            else result = gcd(result, abs(a[i] - a[n - i - 1]));
        }
        if (result == 0x3f3f3f3f) result = 0;
        cout << result << endl;
    }
    return 0;

总结:题目不难,一开始忘记对于两个数让他们mod x后相等,怎么找x了,然后看了测试示例才想起来用大数减去小数得到的数就是要divide它们的数。得到每个数对的x后,直接提交了test2跑不过去,因为一开始的策略是找出所有x中最小的x,但是后来发现这种策略找到的x并不是对于所有的数对都有用的...(也不知道怎么想的,就直接拿去提交了),然后就是改了一下,在查找的过程中不断更新gcd,最后判定一下是inf还是固定数值就好了,题目也不难,就是有些地方欠考虑,太冲了

C. Dreaming of Freedom

题意:n个人给m个算法投票,每轮投票获票最多的算法会留下来,直到只剩最后一个选项为止。问有没有可能这个投票会一直投下去(没有结果)

思路:如果n个人的票数能够平均的分配到m个选项上,那么这个投票就有可能是infinite的,所以问题转变成在2~m的范围内,有没有n的因子,直接暴力得到TLE....

然后需要prone,即将不需要的判定剪掉,因为是对多个数进行判定,而且n的上限为1e6,所以先预处理1~1e3的质数,然后看n在这个范围内有没有质因子即可。


#include <bits/stdc++.h>

using namespace std;

typedef vector<int> vi;
typedef long long int ll;
typedef vector<ll> vll;
typedef pair<int, int> pii;

#define lowbit(S) ((S)& -(S))

bitset<10001>check;
vi sieve(int x){
        vi prime;
        check.set();

        for (int i = 2; i <= x; ++i) if(check[i]){
            for (int j = i * i; j <= x; j += i){
                check[j] = 0;
            }
            prime.push_back(i);
        }
        return prime;

 }
int main(){
 ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int N = 0;
    vi prime = sieve(1e3 + 100);
    cin >> N;
    while (N--){
        int n, m;
        cin >> n >> m;
        if (n == 1 || m == 1){cout << "YES\n";continue;}
        if (n <= m){cout << "NO\n"; continue;}
        bool ok = true;
        for (int i = 0; i < (int)prime.size() && prime[i] <= m; ++i){
            if (n % prime[i] == 0) {ok = false; break;}
        }
        cout << (ok ? "YES" : "NO") << endl;

    }
    return 0;
}

总结:题目不难,难点在于细节的把控,比如如何判断是否有因子,搜索的范围,是否要预处理,特殊情况等

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值