Codeforces Round #698 (Div. 2)(A ~ F)6题全,超高质量题解)【每日亿题】2021/2/4

整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


爱了爱了

【每日亿题】Codeforces Round #698 (Div. 2)(A ~ F)6题全,超高质量题解)2021/2/4

在这里插入图片描述
比赛链接:https://codeforces.com/contest/1478

A - Nezzar and Colorful Balls

Problem A - Nezzar and Colorful Balls

给你 n n n 个球 1 ⋯ n 1\cdots n 1n,每个球上有一个数字,所有球上的数字组成的序列经排序以后是一个不下降的数列。我们要为每一个球都染上颜色,保证我们使用的每一种颜色,染上这个颜色的球上的数字组成的序列经排序后一定是严格上升的数列。问我们最少需要多少种颜色才能在符合要求的前提下将所有的球都染上色。

1 ≤ T , n ≤ 100 1\le T,n\le100 1T,n100

Solution

签到题,只要读懂题意模拟一下样例就行了,我们发现答案就是相同数字的最大个数。因为每个颜色能染的球,球上的数字必须是严格升序而不能是相等,所以也就意味着对于相同数字的球,我们每一种颜色都只能染一个球,最少需要的颜色数量就是相同数字的球的最大数量。我们直接用桶记录一下 ~ 算一下这个最大个数即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const int N = 50007;

int n, m, t;
int a[N];
int ans;
int vis[N];

int main()
{
   
    scanf("%d", &t);
    while(t -- ) {
   
        ans = 0;
        memset(vis, 0, sizeof vis);
        scanf("%d", &n);
        for(int i = 1; i <= n; ++ i) {
   
            scanf("%d", &a[i]);
            vis[a[i]] ++ ;
        }
        for(int i = 1; i <= n; ++ i) {
   
            ans = max(ans, vis[a[i]]);
        }
        printf("%d\n", ans);
    }
    return 0;
}

B - Nezzar and Lucky Number

Problem B Nezzar and Lucky Number

给定 q q q 个正整数,问能不能拆分一个或多个十进制表示法上有 d d d 的正整数。 ( 1 ≤ q ≤ 1 0 4 , 1 ≤ d ≤ 9 1 \le q \le 10^4,1 \le d \le 9 1q104,1d9 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109.

Solution

因为数据比较大,这种题目一般数达到一个限制以后,答案就不会变了。

我们发现一旦 x ≥ 10 ∗ d x\ge 10*d x10d,就一定能被 “幸运数字” 拼出来。

因为 [ 10 ∗ d , 10 ∗ d + 9 ] [10*d,10*d+9] [10d,10d+9] 都是幸运数字,例如 d = 7 d=7 d=7 [ 70 , 79 ] [70,79] [70,79] 均为幸运数字(均含有 d = 7 d=7 d=7),这样我们在 [ 10 ∗ d , 10 ∗ d + 9 ] [10*d,10*d+9] [10d,10d+9] 的基础之上,都加上 d d d ,得到 [ 10 ∗ d + d , 10 ∗ d + 9 + d ] → [ 11 ∗ d , 11 ∗ d + 9 ] , ( 1 ≤ d ≤ 9 ) [10*d+d,10*d+9+d] \to [11*d,11*d+9],(1\le d \le 9) [10d+d,10d+9+d][11d,11d+9],(1d9) 均为 YES。而 10 ∗ d + 9 + d 10*d+9+d 10d+9+d 的下一位,也就是 10 ∗ d + 9 + d + 1 = 12 ∗ d 10*d+9+d+1=12*d 10d+9+d+1=12d,同样是幸运数字,这样我们再在 [ 11 ∗ d , 11 ∗ d + 9 ] [11*d,11*d+9] [11d,11d+9]的基础之上,同样加上 d d d ,以此类推,我们发现只要 x ≥ 10 ∗ d x\ge 10*d x10d ,答案均为 YES

然后我们只需要考虑一下 x ≤ 10 ∗ d x\le10*d x10d 的情况即可。因为 1 ≤ d ≤ 9 1\le d\le9 1d9,所以这些数不会很多,我们只需要预处理一下即可。可以直接爆搜,将所有的YES 数字加起来,标记和也为 YES 或者动规,甚至手动打表,因为最多只有几百个数。

  • 动规预处理版本的AC代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;
const int N = 1e4 + 7, mod = 1e9 + 7;
typedef long long ll;
int n, m, t, x;

map<int, int> ans[N];
int a[N];
bool vis[N];

void solve(int d)
{
   
    ans[d][0] = 1;
    int limit = 10 * d;
    for(int i = 0; 10 * i + d <= limit; ++ i) {
   
        for(int j = 0; 10 * i + d + j <= limit; ++ j) {
   
            ans[d][10 * i + d + j] |= ans[d][j];
        }
    }
    ans[d][0] = 0;
}

void init()
{
   
    for(int i = 1; i <= 9; ++ i) {
   
        solve(i);
    }
}

int d;

int main()
{
   
    scanf("%d", &t);
    init();
    while(t -- ) {
   
        scanf("%d%d", &n, &d);
        for(int i = 1; i <= n; ++ i) {
   
            int x;
            scanf("%d", &x);
            if(x >= 10 * d) {
   
                puts("YES");
            }
            else {
   
                if(ans[d][x]) {
   
                    puts("YES");
                }
                else {
   
                    puts("NO");
                }
            }
        }
    }
    return 0;
}

写题解看别人题解的时候发现的一个思路:

我们发现一个结论:

若这是 a i a_i ai 满足: a i − k ⋅ d a_i - k \cdot d aikd

其中 k ∈ [ 1 , 9 ] k \in [1,9] k[1,9] 的话,它就可以,反则反之。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;
const int N = 1e4 + 7, mod = 1e9 + 7;
typedef long long ll;
typedef int itn;

itn n, m, q, d;
itn t;
int a[N];

bool solve(itn x)
{
   
    if(x >= 10 * d)
        return true;
    for(;x >= d; x -= d)
        if(x % 10 == d)
        return true;
    return false;
}

int main()
{
   
    scanf("%d", &t);
    while(t -- ) {
   
        scanf("%d%d", &q, &d);
        for(int i = 1; i <= q; ++ i) {
   
            itn x;
            scanf("%d", &x);
            if(solve(x))
                puts("YES");
            else puts("NO");
        }
    }
    return 0;
}

C - Nezzar and Symmetric Array

定义长度为 2 × n 2 \times n 2×n 的数组 a a a ,满足:

a a a 中的元素不重复。

并且对于任意一个下标 i ( 1 ≤ i ≤ 2 ⋅ n , i ≠ j ) i(1 \leq i \leq 2 \cdot n, i \ne j) i(1i2n,i=j),都能找到一个下标 j j j,使得 a i = − a j a_i = -a_j ai=aj

现在给定一个数组 d d d,其中

d i = ∑ j = 1 2 n ∣ a i − a j ∣ d_i = \sum_{j=1}^{2n}|a_i -a_j| di=j=12naiaj
问能不能通过数组 d d d 构造出数组 a a a

能构造出输出 YES,不能就输出 NO
T T T 组数据,其中 1 ≤ T ≤ 1 0 5 , 1 ≤ n ≤ 1 0 5 , 1 ≤ d i ≤ 1 0 12 1\le T \le10^5,1\le n \le10^5,1\le d_i\le10^{12} 1T105,1n105,1di1012

并且保证 ( ∑ n ∈  o n e  t e x t  c a s e n ) ≤   1 0 5 (\sum_{n\in\ \text one\ \text text\ \text case} n ) \le\ 10^5 (n one text casen) 105

Solution

一般这种有 n n n 个的数组, n n n 会很大,求一种 v a l u e \tt value value 什么的,一定是一种规律性的问题。

所以我们一般从两个数开始,从特殊到一般,一般简单推一下就能找到拓展到 n n n 个数的答案。

我们首先分析两个的情况。

我们假设两个正整数 a , b a,b a,b

那么序列就会有四个数: a , b , − a , − b a,b,-a,-b a,b,a,b

d 1 = ∣ a − a ∣ + ∣ a − b ∣ + ∣ a − ( − a ) ∣ + ∣ a − ( − b ) ∣ d_1=|a-a|+|a-b|+|a-(-a)|+|a-(-b)| d

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁凡さん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值