牛客挑战赛47 A题
文章目录
- 牛客挑战赛47 A题
- 题目描述
- 输入描述:
- 输出描述:
- 输入
- 输出
- **根据多维的更相减损术得** g c d ( x , y , z ) = g c d ( x , y − x , z − y ) gcd(x,y,z)=gcd(x,y−x,z−y) gcd(x,y,z)=gcd(x,y−x,z−y)
- **可得**: g c d ( a 1 + k , a 2 + k , a 3 + k , . . . , a n + k ) = g c d ( a 1 + k , a 2 − a 1 , a 3 − a 2 , . . . ) gcd(a_1+k,a_2+k,a_3+k,...,a_n+k) = gcd(a_1+k,a_2-a_1,a_3-a_2,...) gcd(a1+k,a2+k,a3+k,...,an+k)=gcd(a1+k,a2−a1,a3−a2,...)
- AC代码:
题目链接: https://ac.nowcoder.com/acm/contest/10743/A
来源:牛客网
题目描述
给定一个数组 a a a。现在让每个数都加上同一个非负整数 k k k,使得所有数的 g c d gcd gcd(最大公约数)尽可能大。
求这个 g c d gcd gcd最大值以及 k k k的值。如果有多个 k k k能得到这个最大的, g c d gcd gcd那么输出 k k k的最小值。
保证数组长度不小于2,且至少有两个不相同的数!
输入描述:
第一行一个正整数
(
2
≤
n
≤
100000
)
(2≤n≤100000)
(2≤n≤100000)
第二行个正整数
a
i
a_i
ai
(
1
≤
a
i
≤
1
0
9
)
(1≤a_i≤10^9)
(1≤ai≤109)
输出描述:
一行两个数,分别代表最终 g c d gcd gcd的最大值、以及达到这个最大值的最小的 。
示例1
输入
2
1 3
输出
2 1
根据多维的更相减损术得 g c d ( x , y , z ) = g c d ( x , y − x , z − y ) gcd(x,y,z)=gcd(x,y−x,z−y) gcd(x,y,z)=gcd(x,y−x,z−y)
可得: g c d ( a 1 + k , a 2 + k , a 3 + k , . . . , a n + k ) = g c d ( a 1 + k , a 2 − a 1 , a 3 − a 2 , . . . ) gcd(a_1+k,a_2+k,a_3+k,...,a_n+k) = gcd(a_1+k,a_2-a_1,a_3-a_2,...) gcd(a1+k,a2+k,a3+k,...,an+k)=gcd(a1+k,a2−a1,a3−a2,...)
那么 根据后面n个数的 g c d gcd gcd来确定 a 1 + k a_1+k a1+k的值(使 a 1 + k a_1+k a1+k为的 g c d gcd gcd的倍数)
a 1 + k = n ∗ g c d a_1+k = n*gcd a1+k=n∗gcd n ∈ ( 1 , 2 , 3 , . . . ) n\in(1,2,3,...) n∈(1,2,3,...)
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 50;
long long a[N];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + n + 1); //先排序
long long gcd = 0;
for (int i = 2; i <= n; i++)
{
gcd = __gcd(gcd, a[i] - a[i - 1]);
}
cout<<gcd<<" ";
//求k的最小值 最初是这么写的
int k=0;
while(1)
{
if((a[1]+k) % gcd == 0) //如果a[1]+k为gcd的倍数 那么此时的k最小
{
cout<<k<<endl;
break;
}
}
return 0;
}
优化了一下求k的过程:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 50;
long long a[N];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + n + 1);
long long gcd = 0;
for (int i = 2; i <= n; i++)
{
gcd = __gcd(gcd, a[i] - a[i - 1]);
}
cout<<gcd<<" ";
//优化代码
int k=0;
while((a[1]+k) % gcd)
k++;
cout<<k<<endl;
return 0;
}
参考大佬的代码:
求最小值k的方式真是妙啊~
如果 a [ 1 ] ≠ n × g c d a[1] ≠ n×gcd a[1]=n×gcd ( n ∈ ( 1 , 2 , 3... ) ) (n\in(1,2,3...)) (n∈(1,2,3...)) g c d − a [ 1 ] gcd-a[1]%gcd gcd−a[1]就是最小值k
如果 a [ 1 ] = g c d a[1] =gcd a[1]=gcd ( n ∈ ( 1 , 2 , 3... ) ) (n\in(1,2,3...)) (n∈(1,2,3...)) 那么 g c d − a [ 1 ] gcd-a[1]%gcd gcd−a[1] 还是 g c d gcd gcd ,需要再对 g c d gcd gcd取余
合成一个式子: ( g c d − a [ 1 ] % g c d ) % g c d (gcd - a[1] \% gcd) \% gcd (gcd−a[1]%gcd)%gcd
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 50;
long long a[N];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + n + 1);
long long gcd = 0;
for (int i = 2; i <= n; i++)
{
gcd = __gcd(gcd, a[i] - a[i - 1]);
}
cout << gcd << " " << (gcd - a[1] % gcd) % gcd << endl;
return 0;
}