Algorithm/math
[백준] 알고리즘 C++ 2981번 - 검문문제
낭강
2022. 1. 19. 17:21
문제
https://www.acmicpc.net/problem/2981
2981번: 검문
트럭을 타고 이동하던 상근이는 경찰의 검문을 받게 되었다. 경찰은 상근이가 운반하던 화물을 하나하나 모두 확인할 것이기 때문에, 검문하는데 엄청나게 오랜 시간이 걸린다. 상근이는 시간
www.acmicpc.net
소스코드
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby,
C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int arr[101];
vector<int> ans;
int gcd(int a,int b){
if(a%b==0){
return b;
}
return gcd(b,a%b);
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>arr[i];
sort(arr,arr+n);
int g=arr[1]-arr[0];
for(int i=2;i<n;i++){
g=gcd(g,arr[i]-arr[i-1]);
}
for(int i=2;i*i<=g;i++){
if(g%i==0){
ans.push_back(i);
ans.push_back(g/i);
}
}
ans.push_back(g);
sort(ans.begin(),ans.end());
ans.erase(unique(ans.begin(),ans.end()),ans.end());
for(int i=0;i<ans.size();i++){
cout<<ans[i]<<" ";
}
}
해설
1. 나머지가 같게 된다.
2. M이 하나 이상 무조건 존재한다.
이 두가지의 키워드를 가지고 문제를 접근해볼 수 있다.
처음 모든 경우의 수의 최대공약수를 구한 후 그 gcd에서 약수를 구해주면 정답이지만, 시간초과가 날게 뻔하다.
우리는 수학적으로 접근해보아야 한다.
a = m*a+r
b=m*b+r
c=m*c+r
여기에서 우리는 나머지가 같다는 것을 알 수 있다. 나머지도 같고 m도 주어진 수들에 대해서 나누었을 때 나머지가 같도록 같은 수라고 생각할 수 있다. 그렇다면 빼보면 어떻게 될까
a-b=m(a-b) + (r-r)
결국 m을 찾기 위해서는 a-b의 최대공약수를 구한 후 약수들이 m이라고 볼 수 있다.
결국 a-b b-c 이런식으로 n 까지 최대공약수를 구해서 약수들을 구해주면 된다.
약수들을 구하고 난 이후에 자기자신을 포함해서 정렬을 한 이후, 중복된 원소를 제거해준다.