Codeforces Round 686 (Div.3)
Updated:
A. Special Permutation
$p_i=i$가 되지 않게 하는 순열을 출력하는 문제 ($1$ ≤ $i$ ≤ $n$)
그냥 2부터 $n$까지 출력한 후 마지막에 1을 출력하면 된다.
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
for(int i=2;i<=n;i++) cout<<i<<' ';
cout<<1<<endl;
}
return 0;
}
B. Unique Bid Auction
유일하고 가장 작은 번호를 선택한 $i$번째 참가자의 인덱스를 출력하는 문제
#include <iostream>
#include <vector>
using namespace std;
int main() {
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
vector<int> cnt(n+1), idx(n+1);
for(int i=0;i<n;i++) {
int x;
cin>>x;
cnt[x]++;
idx[x]=i+1;
}
int ans=-1;
for(int i=0;i<=n;i++) {
if(cnt[i]==1) {
ans=idx[x];
break;
}
}
cout<<ans<<endl;
}
return 0;
}
C. Sequence Transform
배열 $a$에서 $a_i$가 등장한 횟수 + 1이 $a_i$를 제외하고 모두 지우기 위한 실행 횟수이다.
예를들어, 배열 $a = [2, 2, 1, 2, 3, 2, 1, 2, 3, 1, 2]$라고 하자.
먼저, 배열에 같은 숫자가 연속으로 나온 경우는 제외해야 하므로 다음과 같이 바꿔주자.
$a = [2,1,2,3,2,1,2,3,1,2]$
이제 배열에 속한 숫자마다 등장한 횟수를 세어보면 다음과 같다.
- $a_i=1$ 일 때 등장 횟수 3 → 필요한 실행 횟수 = 4
- $a_i=2$일 때 등장 횟수 5 → 필요한 실행 횟수 = 6
- $a_i=3$일 때 등장 횟수 2 → 필요한 실행 횟수 = 3
이때, 배열의 맨 앞에 위치한 숫자의 경우 더 앞은 지울 필요가 없고 맨 뒤에 위치한 숫자의 경우도 그 뒤의 숫자를 지울 필요가 없다. 그래서 맨 앞의 숫자와 맨 뒤의 숫자의 실행 횟수를 각각 -1해준다.
- $a_i=1$ 일 때 등장 횟수 3 → 필요한 실행 횟수 = 4
- $a_i=2$일 때 등장 횟수 5 → 필요한 실행 횟수 = 4
- $a_i=3$일 때 등장 횟수 2 → 필요한 실행 횟수 = 3
따라서, 최소 실행 횟수는 3이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
vector<int> a;
vector<int> res(n+1,1); // n개의 배열로 잡고 1로 초기화
for(int i=0;i<n;i++) {
int x;
cin>>x;
a.push_back(x);
}
// 입력 받을 때 연속인 숫자를 제외해서 받아도 된다.
n=unique(a.begin(),a.end())-a.begin();
a.resize(n);
for(int i=0;i<n;i++) res[a[i]]++;
// a배열의 맨 앞 숫자와 맨 뒤 숫자의 실행 횟수 -1
res[a[0]]--;
res[a[n-1]]--;
int ans=1e9; // 충분히 큰 수
for(int i=0;i<n;i++) ans=min(ans, res[a[i]]);
cout<<ans<<endl;
}
return 0;
}
D. Number into Sequence
입력된 정수 $n$에 대해서 다음 조건을 만족하는 $a$배열을 구하는 문제이다.
- $a_i$는 1보다 커야한다.
- $a_1 \cdot a_2 \cdot a_3 \cdot…\cdot a_k=n$
- $a_{i+1}$은 $a_i$로 나눠질 수 있어야 한다.
- $k$는 최대로 가능한 수여야 한다.
먼저 $n$의 소인수분해를 한 형태는 다음과 같다.
$n = p_1^{b_1} \cdot p_2^{b_2} \cdot … \cdot p_k^{b_k}$
이때, 문제의 정답의 길이는 $b_i$의 최대값을 넘지 못한다. 왜냐하면 문제의 3번 조건때문이다.
예를들어, $n$이 360이라 가정하자. 소인수분해를 한 결과는 다음과 같다.
- $360=2^3\cdot3^2\cdot5$
여기서 4번 조건과 3번 조건으로 인해 2가 가장 많으므로 $a$배열에는 모두 2의 배수여야 한다. 중간에 3이나 5가 나와버리면 3번 조건이 위배되기 때문이다.
그리고 2의 배수는 2가 될 수 있기 때문에 최대한 늘리기 위해서는 2를 연속으로 사용해야 한다.
이런방식으로 다음의 과정을 거칠 수 있다.
- $a=[2,2,2]$
- $a=[2,2,2\cdot3^2]$
- $a=[2,2,2\cdot3^2\cdot5]=[2,2,90]$
따라서, 정답은 [2, 2, 90]이다.
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
int main() {
int t;
cin>>t;
while(t--) {
ll n;
cin>>n;
vector<pair<int,ll> > val;
for(ll i=2; i*i<=n;i++) { // 소인수분해
int cnt=0;
while(n%i==0) {
cnt++;
n/=i;
}
if(cnt>0) val.push_back({cnt, i}); // (지수, 약수)
}
if(n>1) val.push_back({1, n});
sort(val.rbegin(), val.rend()); // 가장 많은 약수가 앞으로 정렬
vector<ll> ans(val[0].first, val[0].second);
for(int i=1;i<val.size();i++) {
for(int j=0;j<val[i].first;j++) ans.back()*=val[i].second;
}
cout<<ans.size()<<endl;
for(auto it : ans) cout<<it<<' ';
cout<<endl;
}
return 0;
}
Comments