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;
}