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

 

1086번: 박성원

첫째 줄에 정답을 기약분수 형태로 출력한다. p/q꼴로 출력하며, p는 분자, q는 분모이다. 정답이 0인 경우는 0/1로, 1인 경우는 1/1로 출력한다.

www.acmicpc.net

 

boj 2098 외판원 순회와 푸는 방식이 조금 비슷하다. 

하지만 그렇다고 방심하면 절대 안된다....

 

 

- 처음에 막혔던 것은

 

23489178492738953489278913278943 % k 를 구하고(a)

그 다음  a 와 38941023890582943829048130248029 를 합친 수 % k 를 구하고(b)....

 

를 좀 더 빠르게 구할 방법이 없을까 이다.

 

답은 na[100][1<<n]를 만들어 행에는 나머지 a , 열은 arr[i] 를 기준으로 메모이제이션을 해주면 된다.

 

 

 

그래서 일단 만들어 봤다.

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
#include <iostream>
#include <algorithm>
#include <string>
#define pii pair<intint>
#define ll long long int
using namespace std;
 
 
string arr[15];
int get_na[100][15]; // i과 arr[i]를 합친 후의 MOD;
int n, na;
ll d[15][1 << 15];
 
 
ll go(int cur, int cur_mod, int visit)
{
    if (visit == (1 << n) - 1)
    {
        if (cur_mod == 0)
            return 1;
        else
            return 0;
    }
 
    if (d[cur][visit] != -1)
        return d[cur][visit];
    else
        d[cur][visit] = 0;
 
    for (int i = 0; i < n; i++)
    {
        if ((visit & (1 << i)) != 0)
            continue;
 
        d[cur][visit] += go(i, get_na[cur_mod][i], visit + (1 << i));
    }
 
    return d[cur][visit];
 
}
 
ll get_GCD(ll a, ll b)
{
    if (b == 0)
        return a;
    else
        get_GCD(b, a % b);
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    cin >> n;
 
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    cin >> na;
    
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < (1 << n); j++)
            d[i][j] = -1;
    }
    for (int i = 0; i < na; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int init = i;
 
            for (int k = 0; k < arr[j].size(); k++)
            {
                init = (init * 10 + (arr[j][k] - '0')) % na;
            }
            get_na[i][j] = init;
        }        
    }
 
    ll ans = 0;
    
    for (int i = 0; i < n; i++)
        ans += go(i, get_na[0][i], 1 << i);
 
//    cout << ans << '\n';
 
    ll can = 1;
    for (int i = 2; i <= n; i++)
        can = can * i;
 
    if (can == ans)
        cout << "1/1";
    else if (ans == 0)
        cout << "0/1";
    else
    {
        ll GCD = get_GCD(can, ans);
        cout << ans/GCD << '/' << can/GCD;
    }    
 
}
cs

 

 

하지만 런타임 에러가 나를 오랫동안 괴롭혔다.

 

한참을 찾은 결과 get_GCD의 함수가 런타임 에러를 뿜었던 것이였다. 아니 왜 저렇게 쓰면 안되는거지????? 

나중에 찾아봐야겠다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ll getGCD(ll a, ll b)
{
    if (b == 0)
        return a;
    else
        getGCD(b, a % b);
} // 안됨
 
 
 
 
ll getGCD(ll a, ll b)
{
    if (a % b == 0)
        return b;
    else
        return getGCD(b, a % b);
} // 됨
cs

 

하지만 뭔가 맞은거 같지만 틀렸다. 그래서 d[][] 부분을 다르게 고쳤다.

개인적인 추측으로는 탑다운 방식을 쓸때 go()함수를 여러번 써서 그런것 같다.

 

 

 

 

 

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
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#define pii pair<intint>
#define ll long long int
using namespace std;
 
string arr[15];
int n, k;
 
ll d[100][1 << 15];
ll na[100][15];
 
 
ll go(int cur_na, int visit)
{
    
    if (visit == (1 << n) - 1)
    {
        if (cur_na == 0)
            return 1;
        else
            return 0;
    }
 
    if (d[cur_na][visit] != -1)
        return d[cur_na][visit];
 
    d[cur_na][visit] = 0;
 
 
    for (int i = 0; i < n; i++)
    {
        if ((visit & (1 << i)) != 0)
            continue;
 
        d[cur_na][visit] += go(na[cur_na][i] ,visit | (1 << i));
    }
 
    return d[cur_na][visit];
}
 
 
 
 
ll getGCD(ll a, ll b)
{
    if (a % b == 0)
        return b;
    else
        return getGCD(b, a % b);
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    cin >>n;
 
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    cin >> k;
 
    for (int i = 0; i < k; i++)
    {
        for (int j = 0; j < (1 << n); j++)
            d[i][j] = -1;
    }
 
 
    for (int i = 0; i < k; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int init = i;
 
            for (int l = 0; l < arr[j].size(); l++)
            {
                init = (init * 10 + (arr[j][l] - '0')) % k;
            }
            na[i][j] = init;
        //    cout << na[i][j] << ' ';
        }
    //    cout << '\n';
    }
 
    
 
 
    ll ans = go(00);
    ll can = 1;
 
    for (ll i = 2; i <= n; i++)
        can *= i;
 
 
 
 
    if (ans == can)
        cout << "1/1";
    else if (ans == 0)
        cout << "0/1";
    else
    {
        ll gcd = getGCD(can, ans);
        cout << (ans / gcd) << '/' << (can / gcd);
    }
}
cs

'뚝배기 터진 문제_boj' 카테고리의 다른 글

boj17387 선분 교차 2  (0) 2020.07.17
boj2618 경찰차  (0) 2020.07.15
boj 2098 외판원 순회  (0) 2020.07.02
boj 9370 미확인 도착지  (0) 2020.07.01
boj 1520 내리막 길  (0) 2020.06.25

+ Recent posts