当前位置:   article > 正文

Codeforces Round #698 (Div. 2)A,B,C,D,F_d |i鈭抝|=|ai鈭抋j|

d |i鈭抝|=|ai鈭抋j|

Codeforces Round #698 (Div. 2)A,B,C,D,F

A - Nezzar and Colorful Balls

题意

n n n 个球,第 i i i 个球上的序号是 a i a_i ai ,保证对任意 a i a_i ai 都有 a i ≤ a i + 1 a_i \leq a_{i+1} aiai+1 。现在你要给球涂上颜色,保证在球按照颜色分开后,每种颜色的球序号从小到大是严格递增的,也就是只考虑某种颜色的球的情况下,对相邻的 a i a_i ai a j a_j aj,均有 a i < a i + 1 a_i \lt a_{i+1} ai<ai+1 。问最少需要几种颜色,能达到这个要求?

思路

问题可以化为:原数组中有可能有多个重复相同的数字,分开后的数组中不能有重复相同的数字。因此,只需要找到原数组所有元素中出现次数最多的即可。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e6 + 9;
const ll mod = 1e9 + 7;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        int nowcnt = 0;
        int maxc = 0;
        int nowx = 0;
        for(int i = 0; i < n; i++)
        {
            int x;
            scanf("%d", &x);
            if(x != nowx)
            {
                maxc = max(maxc, nowcnt);
                nowx = x;
                nowcnt = 1;
            }
            else
            {
                nowcnt++;
            }
        }
        cout << max(maxc, nowcnt) << endl;
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

B - Nezzar and Lucky Number

题意

在1~9中,李华最喜欢的数字是 d d d 。如果一个正整数在其十进制表示下含有 d d d ,则李华称之为幸运数字。现给定一些数字,问你他们能否被分解为几个(一个或多个)幸运数字相加?

思路

  1. 如果数字 x x x 大于等于 10 × d 10 \times d 10×d ,则 x x x 一定可以分解成 x = ( k 1 × 1 0 m + d ∗ 10 + k 2 ) + ( k 3 × 10 + d ) x = (k_1 \times10^m + d*10 + k_2) + (k_3 \times 10 + d) x=(k1×10m+d10+k2)+(k3×10+d) 的形式( k i k_i ki 是任意正整数),这两个数都含有数字d(一个在十位一个在个位);
  2. 在数字 x x x 小于 10 × d 10 \times d 10×d 的情况下,则 x x x 若能被分解,一定有 x = k 1 × 10 + k 2 × d x = k_1 \times 10 + k_2 \times d x=k1×10+k2×d,因此只需要判断 x x x 的个位是否与某一个 d d d 的倍数的个位相同即可。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e6 + 9;
const ll mod = 1e9 + 7;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int q, d;
        scanf("%d%d", &q, &d);
        for(int i = 0; i < q; i++)
        {
            bool flag = 0;
            ll x;
            scanf("%lld", &x);
            if(x >= 10 * d)
            {
                printf("YES\n");
                continue;
            }
            int tmp = x % 10;
            for(int i = 1; i < 10; i++)
            {
                if(i * d > x)
                    break;
                if(i * d % 10 == tmp)
                {
                    flag = 1;
                    break;
                }
            }
            if(flag)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

C - Nezzar and Symmetric Array

题意

数组 a a a 中有 2 n 2n 2n 个整数,且数组中的元素满足,若 a i a_i ai 在数组中,则必有且仅有一个 a j = a i a_j = a_i aj=ai,即每个数的相反数都在其中。现给定一个数组 d d d ,其中 d i = ∑ j = 1 n ∣ a i − a j ∣ d_i = \sum_{j = 1}^n |a_i - aj| di=j=1naiaj,问能不能推出一个满足要求的数组 a a a ?无需输出 a a a 的内容,只需要判断。

思路

参考:

Codeforces Round #698 (Div. 2)-C. Nezzar and Symmetric Array-题解

Codeforces Round #698 (Div. 2)_

我们可以思考: d d d a a a 有哪些相关的特性?

  1. a a a 的每一个元素在 d d d 中对应位置的值,与他的相反数在 d d d 中对应位置的值,都是相等的。这点可以通过假设法证明(假设有 a < b < c ( a , b , c > 0 ) a < b < c(a,b,c \gt 0) a<b<c(a,b,c>0),计算 a a a − a -a a b b b − b -b b c c c − c -c c d d d 中的值);
  2. 对于任意的 a i a_i ai ,其与除自身外的任意元素 a j a_j aj ,都有 ∣ a i − a j ∣ + ∣ a i − ( − a j ) ∣ |a_i - a_j| + |a_i - (-a_j)| aiaj+ai(aj) 的值一定是偶数(分类讨论或者画图一下即可);
  3. 原本的每一个数都是整数;
  4. 若只考虑正整数(或只考虑负整数),每一个数都是独特的,没有重复。这点可以合并到第1点去(见下面的概括)。

综上,我们可以把特性概括/衍生为以下几点:

  1. d d d 中每个元素的值出现且仅出现两次(第一点+第四点);
  2. d d d 中的每个元素都是偶数;
  3. 原本的数都是整数。

第一点和第二点通过map来实现,因为数据范围1e9,数组存不下;

第三点,我们分类讨论一下,对于任意的 ∣ a i − a j ∣ + ∣ a i − ( − a j ) ∣ |a_i - a_j| + |a_i - (-a_j)| aiaj+ai(aj) ,如果 a i > a j a_i \gt a_j ai>aj,则 ∣ a i − a j ∣ + ∣ a i − ( − a j ) ∣ = 2 a i |a_i - a_j| + |a_i - (-a_j)| = 2a_i aiaj+ai(aj)=2ai;若 a i < a j a_i \lt a_j ai<aj,则 ∣ a i − a j ∣ + ∣ a i − ( − a j ) ∣ = 2 a j |a_i - a_j| + |a_i - (-a_j)| = 2a_j aiaj+ai(aj)=2aj。所以其实 d i d_i di就是 2 × ∑ j = 0 n m a x ( a i , a j ) 2 \times \sum_{j = 0}^n max(a_i, a_j) 2×j=0nmax(ai,aj),即 a i a_i ai 和其他所有正整数比较后最大的那个正整数的两倍,所以在已知 d i d_i di的情况下, a i = ( d i / 2 − s u m / n ) a_i = (d_i/2- sum/n) ai=(di/2sum/n),其中 s u m = ∑ a j , a j > a i sum = \sum a_j, a_j \gt a_i sum=aj,aj>ai 。所以从大到小不重复的遍历所有 d i d_i di,将当前元素减去之前已经算出的元素(因为是从最大开始算,所以 s u m sum sum 的值其实就是之前元素的累加),再除以还剩下几个元素,判断是否能整除(且大于0)即可。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e6 + 9;
const ll mod = 1e9 + 7;

map<ll, int> mp;
priority_queue<ll> que;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        mp.clear();
        while(!que.empty())
            que.pop();
        int n;
        scanf("%d", &n);
        for(int i = 0; i < 2 * n; i++)
        {
            ll x;
            scanf("%lld", &x);
            mp[x]++;
        }
        bool flag = true;
        for (auto i : mp)
        {
            que.push(i.first);
            if (i.second != 2)
            {
                flag = false;
                break;
            }
        }
        if (!flag || que.size() != n)
        {
            cout << "NO" << endl;
            continue;
        }
        ll sum = 0;
        for(int i = n; i >= 1; i--)
        {
            ll x = que.top();
            que.pop();
            if(x - sum <= 0 || ((x - sum) % (2 * i)) != 0)
            {
                flag = false;
                break;
            }
            else
            {
                sum += (x - sum) / i;
            }
        }
        if (flag)
        {
            cout << "YES" << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

D - Nezzar and Board

题意

黑板上有 n n n 个不同的整数,可以进行的操作是选取两个数 x , y x,y x,y,将 2 x − y 2x-y 2xy 放回黑板(不删除选取的数)。问能否经过一系列的操作得出给定的 k k k

思路

参考:Codeforces Round #698 (Div. 2) D. Nezzar and BoardCodeforces Round #698 (Div. 2) A~F

裴蜀定理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Np3gOfTy-1612356393165)(C:\Users\29039\AppData\Roaming\Typora\typora-user-images\image-20210201161808476.png)]

把操作看成 x + ( x − y ) x + (x - y) x+(xy),则整个过程化为元素 x x x 加上两个数的差值。又,形如 a 3 − a 1 a_3 - a_1 a3a1 的差可以转换为 a 3 − a 2 + a 2 − a 1 a_3 - a_2 + a_2 - a_1 a3a2+a2a1,所以任何差 a n − a m a_n - a_m anam 都能化为 ∑ i = 1 n − 1 ( a i + 1 − a i − ∑ i = 1 m − 1 ( a i + 1 − a i ) \sum_{i = 1}^{n - 1}(a_{i + 1} - a_i - \sum_{i = 1}^{m - 1}(a_{i + 1} - a_i) i=1n1(ai+1aii=1m1(ai+1ai) 的形式,所以我们可以将 2 x − y = k 2x - y = k 2xy=k 转化为:
a 1 + k 1 ∗ ( a 2 − a 1 ) + k 2 ∗ ( a 3 − a 2 ) + … + k n − 1 ∗ ( a n − a n − 1 ) = k a_1 + k_1* (a_2 - a_1) + k_2* (a_3 - a_2) + …+ k_{n - 1}* (a_n - a_{n - 1}) = k a1+k1(a2a1)+k2(a3a2)++kn1(anan1)=k

k 1 ∗ ( a 2 − a 1 ) + k 2 ∗ ( a 3 − a 2 ) + … + k n − 1 ∗ ( a n − a n − 1 ) = k − a 1 k_1* (a_2 - a_1) + k_2* (a_3 - a_2) + …+ k_{n - 1}* (a_n - a_{n - 1}) = k - a_1 k1(a2a1)+k2(a3a2)++kn1(anan1)=ka1

的形式。

因此,只要存在 a i a_i ai,有其他所有数字的最大公约数等于 k − a i k - a_i kai,原式就成立。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 3e5 + 19;
const ll mod = 1e9 + 7;

ll a[N];

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int n;
        ll k;
        cin >> n >> k;
        ll gcd = 0;
        for(int i = 0; i < n; i++)
        {
            cin >> a[i];
            if(i < 1)
                continue;
            if(i == 1)
            {
                gcd = a[i] - a[i - 1];
                continue;
            }
            gcd = __gcd(gcd, a[i] - a[i - 1]);
        }
        bool flag = 0;
        for(int i = 0; i < n; i++)
        {
            if((k - a[i]) % gcd == 0)
            {
                flag = 1;
                break;
            }
        }
        if(flag)
            cout << "YES\n";
        else
            cout << "NO\n";
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

F - Nezzar and Nice Beatmap

题意

给定 n n n 个点,对其进行重新排列,使之任意连续的三个点形成的角(以中间的点为顶点)小于 90 90 90 度。

思路

参考:Codeforces Round #698 (Div. 2) - Zeronera - 博客园

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e4 + 19;
const ll mod = 1e9 + 7;

struct node
{
    double x;
    double y;
    node(){}
    node(double a, double b){x = a; y = b;}
}a[N];

bool vis[N];

double dis(node a, node b)
{
    return sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
}

int main()
{
    int n;
    queue<int> ans;
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
    {
        scanf("%lf%lf", &a[i].x, &a[i].y);
    }
    int cnt = 0;
    int id = 0;
    vis[0] = 1;
    do
    {
        double maxdis = 0;
        int num = 0;
        ans.push(id + 1);
        for(int j = 0; j < n; j++)
        {
            if(vis[j])
                continue;
            double tmp = dis(a[id], a[j]);
            if(tmp > maxdis)
            {
                maxdis = tmp;
                num = j;
            }
        }
        id = num;
        vis[id] = 1;
        cnt++;
    }
    while(cnt < n);
    while(!ans.empty())
    {
        printf("%d", ans.front());
        ans.pop();
        if(!ans.empty())
            printf(" ");
    }
    printf("\n");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

总结

  1. B题因为一个特判(大于十倍的d的情况)卡了很久WA了两发,还是太不熟练了;
  2. 总体感觉蛮怪的,其实觉得发挥的很差,或许是几页的in queue助攻了一下,总之上分上的很不自在
  3. 虽然每次都说不要死磕前面的题,但是每次都忍不住死磕,,,希望下次能有一丢丢改进

多多包涵,共同进步

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/75433
推荐阅读
相关标签
  

闽ICP备14008679号