2022-03-21每日刷题打卡

2022-03-21每日刷题打卡

力扣春季赛开始啦,佬们求求给战队点个赞吧(每天都可以点的):啊哈哈哈AC来咯

代码源——每日一题

代码源每日一题Div2 - 课程 - Daimayuan Online Judge
题目描述

有n个玩家参加比赛,他们分别有能力值a1,a2,…,an。

需要进行n−1轮比赛,每一轮在剩下的玩家里任选两个玩家i,j。如果|ai−aj|>K,那么其中能力值高的玩家会获胜,能力值低的玩家会被淘汰。如果|ai−aj|≤K,那么两个玩家都有可能获胜,另一个玩家被淘汰。

n−1轮比赛之后,只剩下一个玩家。问有多少个玩家可能是最后获胜的玩家。

输入格式

第一行,两个整数n,K,表示玩家的总人数,和获胜条件中的参数。

接下来一行n个整数a1,a2,…,an,表示玩家的能力值。

输出格式

一个整数,表示最后可能获胜的玩家个数。

样例输入1
5 3
1 5 9 6 3
样例输出1
5

这题估摸着很多人对于 **“ 如果|ai−aj|≤K,那么两个玩家都有可能获胜,另一个玩家被淘汰 ”**这句话有点疑惑,其实你可以这么理解,如果|ai−aj|≤K,那就由拥有上帝视角的我们来决定谁赢谁输就行,我们这里也就是根据这个来算的最多可能有多少人能胜出。虽然判断获胜的条件有两个,但其实第一个基本用不上,你可以这么想:

能力最大的玩家和能力第二大的玩家,如果他们的差值大于k,那就是最大的获胜,而既然第二大的都赢不了,那不用想其它能力更小的了,这样最终胜出的只能是1个:能力最大的玩家;

但如果第二大的玩家和最大的玩家相差小于等于k,那么这两位都可以胜出,而且只要第三大的和第二大的相差也是小于等于k,那么他们三个人都有可能会获胜:第一大和第二大比完,我们让第二大赢,再让第二大和第三大比,我们让第三大赢。同理第四大也可以以此类推……

由此可推,我们可以知道,最大的获胜人数就是看从最大的能量开始推,看有多少个连着的差都是小于等于k,当有差大于k时,就断开了,因为差值一旦大于k,那么只有大的哪个能赢,小的是无论如何不能活到最后的。小的想赢只能靠我们上帝视角来帮忙,这就必须要差值小于等于k。

(这里写了自定义排序规则让sort降序排,其实没必要这么写,只是个人的习惯)

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

#define endl '\n';
typedef long long ll;
typedef pair<int, int>PII;

bool cmp(int a, int b)
{
    return a > b;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, k;
    cin >> n >> k;
    vector<int>v(n);
    for (int i = 0; i < n; i++)
        cin >> v[i];
    sort(v.begin(), v.end(),cmp);
    int res = 1;
    for (int i = 0; i < n-1; i++)
    {
        if (v[i] - v[i + 1] <= k)res++;
        else break;
    }
    cout << res << endl;
    return 0;
}
平方计数 - 题目 - Daimayuan Online Judge
题目描述

给N个正整数, 第ii个数用ai来表示, 求出有多少对(i,j)(i,j) 使得ai^2+aj是一个完全平方数.

输入格式

第一行一个正整数n 第二行n个数, 表示a1,a2,a3…an.

输出格式

一行一个整数, 表示答案

数据范围

对于所有测试数据 满足1≤n≤10^6, 且1≤ai≤10^6

样例输入
5
1 2 3 4 5
样例输出
2

看到这题第一反应,枚举ai,再枚举bi,计算ai^2+bi是不是完全平方数,但很显然1e6的数据要超时。遂想到能不能反向逆着来,我枚举可能的完全平方数,然后根据ai去求bi,但一开始想法有问题,觉着复杂度和枚举bi差不多,幸得群里大佬(某墨镜白猫猫)解惑才想明白。

我们先预处理,数组f记录下每个数的出现次数,顺便记录下最大的max_num(作为枚举时的上界),然后从1开始枚举a,一直枚举到max_num,在来枚举完全平方数。因为a2+b=c2,那么b=c2-a2。所以我们从a开始枚举c,之前记录的最大值max_num就是b的上界(最大也不会大过max_num)。在此区间内枚举c,求出b后,再根据之前记录的a的数量和b的数量,看能有多少数对组合(其实就是f[a]*f[b]个)。

然后我们说下为什么枚举完全平方数会不超时,比如a是1开始,b最大取到1e6,

c2-a2=1e6 ——> c^2-1<=1e6 ——> c=1e3,由此可以看出,即使是最大的情况,c也仅仅枚举了1000次这样,而且随着a的增长,c枚举的范围也会变小。

如果a从1枚举到1e6,b最大取到1e6,那么c总的枚举次数就是:

c2-a2<=1e6
a<=1e6;
a^2<=1e12;
c^2-1e12<=1e6;
c^2<=1e12+1e6;
c 约= 4*1e6

这样一算,我们总程序的只用跑4*1e6就可以得出结果,而c++1秒内可以跑的数据大概是1e8到1e9这样,显然不会超时。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

#define endl '\n';
typedef long long ll;
typedef pair<int, int>PII;
const int N = 1e6 + 50;
int f[N];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n;
    cin >> n ;
    vector<int>v(n);
    int max_num = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> v[i];
        max_num = max(max_num, v[i]);
        f[v[i]]++;
    }
    int res = 0;
    for (int i = 1; i <= max_num; i++)
    {
        if (f[i] == 0)continue;
        for (int j = i + 1; (j - i) * (j + i) <= max_num;j++)
        {
            res += f[i]*f[(j - i) * (j + i)];
        }
    }
    cout << res << endl;
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值