본문 바로가기

백준/수학

백준 2378 - 불필요한 수

728x90

https://www.acmicpc.net/problem/2378

 

문제에 주어진 N에서 일부 값에 대해 수열의 원소 $R_{i}$가 등장하는 횟수를 계산해 보면 이는 파스칼의 삼각형과 동일한 형태를 가짐을 파악할 수 있다.

 

그러면 길이가 N일 때 수열의 원소가 최종적으로 등장하는 횟수를 이항계수로 표현하면

 

$$Count(R) = \{ {N - 1 \choose 0}, {N - 1 \choose 1}, ..., {N - 1 \choose N - 1}  \}$$

 

으로 나타낼 수 있다.

 

그러면 N까지의 원소에서 이항계수를 구했을 때 나머지 M에 나눠떨어지는지 확인하면 되는데 $MAX(M) = 10^{9}$이고 M이 소수라는 조건이 없으므로 이를 처리하기 어려울 수 있다.

 

이를 처리하기 위해 양의 정수는 소인수의 곱으로 나타낼 수 있음을 이용하자.

 

그러면 $M = p_{1}^{a} \times p_{2}^{a} \times ...$으로 바꿀 수 있고 위 이항 계수들 역시 소인수의 곱으로 나타내어 M의 소인수 곱들에 나눠 떨어지는지 확인하는 것으로 모듈러 문제를 처리할 수 있다.

 

map 형태로 소인수 곱의 누적합을 계산하되, 모든 수에 대해 소인수 분해를 하면 시간 초과를 받을 수 있으므로 M의 소인수에 대해서만 계산하도록 하면 빠르게 확인이 가능하다.

 

정답 코드 - CPP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#pragma GCC target("avx,avx2,fma,bmi,bmi2,lzcnt,popcnt")
#pragma GCC optimize("O3,unroll-loops")
 
#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
 
using namespace std;
using namespace __gnu_pbds;
 
using pii = pair<intint>;
using ll = int_fast64_t;
 
ll n, m;
map<intint> p_count;
map<intint> pref[100001];
 
int spf[100001];
 
void sieve(int mx)
{
  for (int i = 2; i <= mx; i++)
  {
    if (spf[i]) continue;
    spf[i] = i;
    for (int j = i * 2; j <= mx; j += i)
    {
      spf[j] = i;
    }
  }
}
 
void solve()
{
  cin >> n >> m;
 
  if (n == 1)
  {
    cout << 0;
    return;
  }
 
  sieve(n);
 
  int mm = m;
  for (ll i = 2; i * i <= mm; i++)
  {
    while (mm % i == 0)
    {
      ++p_count[i];
      mm /= i;
    }
  }
 
  if (mm != 1)
  {
    ++p_count[mm];
  }
 
  pref[2][2= 1;
  for (int i = 3; i <= n; i++)
  {
    int ii = i;
    pref[i] = pref[i - 1];
 
    while (spf[ii])
    {
      int x = spf[ii];
      
      if (p_count.count(x))
      {
        ++pref[i][x];
      }
      
      ii /= x;
    }
 
    if (ii != 1++pref[i][ii];
  }
 
  vector<int> ans;
 
  for (int i = 2; i < n; i++)
  {
    bool divided = true;
    auto mp = pref[n - 1];
 
    for (auto &[k, v] : pref[i - 1])
    {
      mp[k] -= v;
    }
 
    for (auto &[k, v] : pref[n - 1 - i + 1])
    {
      mp[k] -= v;
    }
 
    for (auto &[k, v] : p_count)
    {
      if (mp.count(k) == false or mp[k] < v)
      {
        divided = false;
        break;
      }
    }
 
    if (divided)
    {
      ans.push_back(i);
    }
  }
 
  cout << ans.size() << '\n';
  for (int i : ans) cout << i << ' ';
}
 
int main()
{
#ifdef LOCAL
//  freopen("input.txt", "r", stdin);
  freopen("output.txt""w", stdout);
#endif
 
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  solve();
}
cs

 

728x90

'백준 > 수학' 카테고리의 다른 글

백준 12994 - 이동 3-2  (0) 2025.01.22
백준 31002 - 그래프 변환  (0) 2025.01.11
[ICPC] 백준 28152 - Power of Divisors  (0) 2024.11.27
백준 27437 - 분수찾기 2  (1) 2024.11.13
백준 18287 - 체스판 이동  (0) 2022.08.27