Codeforces Round #686 (Div.3)

65930 단어 Div3pscodeforcesDiv3

A. Special Permutation


pi=ip_i=i

그냥 2부터 nn까지 출력한 후 마지막에 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


유일하고 가장 작은 번호를 선택한 ii번째 참가자의 인덱스를 출력하는 문제

#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


배열 aa에서 aia_i

예를들어, 배열 a=[2,2,1,2,3,2,1,2,3,1,2]a = [2, 2, 1, 2, 3, 2, 1, 2, 3, 1, 2]

먼저, 배열에 같은 숫자가 연속으로 나온 경우는 제외해야 하므로 다음과 같이 바꿔주자.

a=[2,1,2,3,2,1,2,3,1,2]a = [2,1,2,3,2,1,2,3,1,2]

이제 배열에 속한 숫자마다 등장한 횟수를 세어보면 다음과 같다.

  • ai=1a_i=1
  • ai=2a_i=2
  • ai=3a_i=3

이때, 배열의 맨 앞에 위치한 숫자의 경우 더 앞은 지울 필요가 없고 맨 뒤에 위치한 숫자의 경우도 그 뒤의 숫자를 지울 필요가 없다. 그래서 맨 앞의 숫자와 맨 뒤의 숫자의 실행 횟수를 각각 -1해준다.

  • ai=1a_i=1
  • ai=2a_i=2
  • ai=3a_i=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


입력된 정수 nn에 대해서 다음 조건을 만족하는 aa배열을 구하는 문제이다.

  1. aia_i
  2. a1a2a3...ak=na_1 \cdot a_2 \cdot a_3 \cdot...\cdot a_k=n
  3. ai+1a_{i+1}
  4. kk는 최대로 가능한 수여야 한다.

먼저 nn의 소인수분해를 한 형태는 다음과 같다.

n=p1b1p2b2...pkbkn = p_1^{b_1} \cdot p_2^{b_2} \cdot ... \cdot p_k^{b_k}

이때, 문제의 정답의 길이는 bib_i

예를들어, nn이 360이라 가정하자. 소인수분해를 한 결과는 다음과 같다.

  • 360=23325360=2^3\cdot3^2\cdot5

여기서 4번 조건과 3번 조건으로 인해 2가 가장 많으므로 aa배열에는 모두 2의 배수여야 한다. 중간에 3이나 5가 나와버리면 3번 조건이 위배되기 때문이다.

그리고 2의 배수는 2가 될 수 있기 때문에 최대한 늘리기 위해서는 2를 연속으로 사용해야 한다.

이런방식으로 다음의 과정을 거칠 수 있다.

  • a=[2,2,2]a=[2,2,2]
  • a=[2,2,232]a=[2,2,2\cdot3^2]
  • a=[2,2,2325]=[2,2,90]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;
}

좋은 웹페이지 즐겨찾기