Codeforces Round #698 (Div. 2)——C、D

C. Nezzar and Symmetric Array

Long time ago there was a symmetric array 𝑎1,𝑎2,…,𝑎2𝑛 consisting of 2𝑛 distinct integers. Array 𝑎1,𝑎2,…,𝑎2𝑛 is called symmetric if for each integer 1≤𝑖≤2𝑛, there exists an integer 1≤𝑗≤2𝑛 such that 𝑎𝑖=−𝑎𝑗.
For each integer 1≤𝑖≤2𝑛, Nezzar wrote down an integer 𝑑𝑖 equal to the sum of absolute differences from 𝑎𝑖 to all integers in 𝑎, i. e. 𝑑𝑖=∑2𝑛𝑗=1|𝑎𝑖−𝑎𝑗|.
Now a million years has passed and Nezzar can barely remember the array 𝑑 and totally forget 𝑎. Nezzar wonders if there exists any symmetric array 𝑎 consisting of 2𝑛 distinct integers that generates the array 𝑑.
Input
The first line contains a single integer 𝑡 (1≤𝑡≤105) — the number of test cases.
The first line of each test case contains a single integer 𝑛 (1≤𝑛≤105).
The second line of each test case contains 2𝑛 integers 𝑑1,𝑑2,…,𝑑2𝑛 (0≤𝑑𝑖≤1012).
It is guaranteed that the sum of 𝑛 over all test cases does not exceed 105.
Output
For each test case, print “YES” in a single line if there exists a possible array 𝑎. Otherwise, print “NO”.
You can print letters in any case (upper or lower).
Example
input
6
2
8 12 8 12
2
7 7 9 11
2
7 11 7 11
1
1 1
4
40 56 48 40 80 56 80 48
6
240 154 210 162 174 154 186 240 174 186 162 210
output
YES
NO
NO
NO
NO
YES

题目分析:
由于每个di是ai与aj差的绝对值,很容易联想到坐标轴上点之间的距离。观察可得规律:
一个较大的数到两个较小的数的距离和等于其自身二倍;一个绝对值较小的数和两个绝对值比它大的正负数的距离和=二倍大数的绝对值。
因为ai每一种值成对出现,所以只需判断a的一种正数序列是否存在。
将d从大到小排序,假设正数序列a也从大到小排序。d0是最大的那个数a0与其他数的距离和,d1是第二大的数与其他数的距离和减去a0的两倍…以此类推可求a的一个从大到小的序列。只需判断是否满足以下条件:
1、di均是偶数,每种值成对出现
2、ai为整数,且>0
3、ai之间互异

AC代码:

#include <string.h>
#include <math.h>
#include<algorithm>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef long long ll;
int main()
{
    int t;
    cin>>t;
    for(; t>0;t--){
        int n;  bool ok=0;
        scanf("%d",&n);
        ll d0[2*n+10], fr=0, d[n+10], a[n+10];//fr即front,比ai前数和
        for(int i=0; i<n*2; i++) scanf("%lld",&d0[i]);
        sort(d0,d0+2*n,greater<ll>() );
        //判断d0i是否成对且为偶,并只保留d0i每种值的一个
        for(int i=0, j=0; i<n*2; i+=2) {
            if( d0[i]!=d0[i+1] || d0[i]%2 ) { ok=1; break; }
            d[j++]=d0[i];
        }
        if(ok) { cout<<"NO"<<endl; continue; }
        for(int i=0;i<n;i++){
            a[i]=(d[i]/2-fr)/(n-i);
            if( (d[i]/2-fr)%(n-i) || a[i]<=0 || ( i>0 && a[i]==a[i-1] ) ) { ok=1; break; }
            fr+=a[i];
        }
        if(ok) { cout<<"NO"<<endl; continue; }
        cout<<"YES"<<endl;
    }
    return 0;
}

D. Nezzar and Board

𝑛 distinct integers 𝑥1,𝑥2,…,𝑥𝑛 are written on the board. Nezzar can perform the following operation multiple times.
Select two integers 𝑥,𝑦 (not necessarily distinct) on the board, and write down 2𝑥−𝑦. Note that you don’t remove selected numbers.
Now, Nezzar wonders if it is possible to have his favorite number 𝑘 on the board after applying above operation multiple times.
Input
The first line contains a single integer 𝑡 (1≤𝑡≤105) — the number of test cases.
The first line of each test case contains two integers 𝑛,𝑘 (2≤𝑛≤2⋅105, −1018≤𝑘≤1018).
The second line of each test case contains 𝑛 distinct integers 𝑥1,𝑥2,…,𝑥𝑛 (−1018≤𝑥𝑖≤1018).
It is guaranteed that the sum of 𝑛 for all test cases does not exceed 2⋅105.
Output
For each test case, print “YES” on a single line if it is possible to have 𝑘 on the board. Otherwise, print “NO”.
You can print each letter in any case (upper or lower).
Example
input
6
2 1
1 2
3 0
2 3 7
2 -1
31415926 27182818
2 1000000000000000000
1 1000000000000000000
2 -1000000000000000000
-1000000000000000000 123
6 80
-5 -20 13 -14 -2 -11
output
YES
YES
NO
YES
YES
NO
Note
In the first test case, the number 1 is already on the board.
In the second test case, Nezzar could perform the following operations to write down 𝑘=0 on the board:
Select 𝑥=3 and 𝑦=2 and write down 4 on the board.
Select 𝑥=4 and 𝑦=7 and write down 1 on the board.
Select 𝑥=1 and 𝑦=2 and write down 0 on the board.
In the third test case, it is impossible to have the number 𝑘=−1 on the board.

题解:
裴蜀定理,现学现卖一波。
在这里插入图片描述本题符合n个整数间的裴蜀定理。
2x-y可以看做是x+(x-y)
将x移到等号右边,题目可化简为:是否存在整数ki (1<=i<n) 使 k1*(a1-a0)+k2*(a2-a1)+…+k[n-1]*(a[n-1]-an)=k-ai
倘若直接求出任意对ai-aj (i!=j),Ω(n^2)
因为对任意ai-aj (i!=j,假设i>j) 可由 a[i] - a[i-1] + a[i-2] - a[i-3] …+ a[j+1] - a[j] ,所以简化后Ω(n)
其次还要注意,计算过程中的数都是正整数

AC代码:

#include <string.h>
#include <math.h>
#include<algorithm>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef long long ll;
//库函数__gcd()不知道为什么我的vs识别不了,就自己写了一个
ll gcd(ll a, ll b){
    ll t;
    if(a<b) { t=a; a=b; b=t; }
    t=a%b;
    while(t) { a=b; b=t; t=a%b; }
    return b;
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        ll k;
        bool ok=0;
        scanf("%d %lld", &n, &k);
        ll a[n+10];
        memset(a, 0, sizeof(a));
        for(int i=0; i<n; i++) scanf("%lld", &a[i]);
        sort(a, a+n);
        ll g=a[1]-a[0];
        //n=1时,g为负数,为了排除这种情况,我多加了个绝对值。我发现别人的代码有的令g=0,但我的编译器那样会运算错误不明原因....
        g=abs(g);
        for(int i=2; i<n; i++){
            g=gcd( (a[i]-a[i-1]), g );
        }
        for(int i=0; i<n; i++){
            if( (k-a[i])%g==0 ) { ok=1; break; }
        }
        if(ok) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值