[BOJ 16808] Identity Function

2022. 2. 14. 16:26PS/백준

함수 $f$는 다음과 같이 정의된다.

\[f(a)=a^{N} \pmod{N}\]

\[F_{1}(a)=f(a)\]

\[F_{k+1}(a)=F_{k}(f(a)) (k=1,2,3,...)\]

이를 간단히 하면 다음과 같다.

\[F_{k}(a)=a^{N^{k}} \pmod{N}\]

이때 $F_{k}(a)=a$인 최소의 $k$를 찾는 것이 우리의 목표이다.

 

먼저 $N=p$(소수)일 경우를 생각해보자.

\[a^{N^{k}} \equiv a \pmod{N}\]

이때 $gcd(a,N)=1$이므로 

\[a^{N^{k}-1} \equiv 1 \pmod{N}\]

\[N^{k} \equiv 1 \pmod{\phi(N)}\]

만약 이때 $\gcd(N,\phi(N))=1$이 아니라면 만족하는 $k$가 존재하지 않는다. $k$가 존재한다면 그 값은 $\phi(\phi(N))$이다.

 

$N=p^{2}l$($p \nmid l$,$p$는 소수)일 경우를 보자. 

$\gcd(a,N)=1$이면 

\[a^{N^{k}-1} \equiv 1 \pmod{N}\]

\[N^{k} \equiv 1 \pmod{\phi(N)}\]

이때 $\gcd(N, \phi(N))>1$이므로 만족하는 $k$가 없다. $a$가 $N$과 서로소가 아닐 경우를 확인하는 것은 의미가 없다.(모든 자연수 $a$에 대해 성립하는 $k$여야 한다.) 

 

이제 남은 경우는 여러 소수들이 한 번씩 곱해진 경우다. 

$N=p_{1}p_{2}...p_{m}$이라 두자.($p_{i}$은 소수, $m$은 자연수) $\gcd(a,N)=\alpha$라 둔다면 $\phi(\phi(N/\alpha))$와 $N$이 서로소일 경우 $k=\phi(\phi(N/\alpha))$이고 아닐 경우 $k$는 존재하지 않는다.

 

$N$의 소인수를 찾고 $\alpha$ 값을 $N$의 가능한 모든 소인수의 곱으로 설정하면서 $k$ 값을 찾아나가면 된다. $k$가 문제의 조건을 만족한다면 $uk$($u$는 자연수)역시 문제의 조건을 만족하므로 여러개의 $k$가 나온다면 그들의 최소공배수를 구해주면 된다. 앞서 한 논의에 의해 구해진 $k$값은 최솟값이 아닐 수 있다. 따라서 $k$의 소인수를 구하여 $k$의 크기를 줄여가며 $1$부터 $\sqrt{N}$까지의 $a$에 대해 식이 성립하는지 확인하면 최솟값을 구할 수 있다. $\sqrt{N}$까지의 값 만으로 판별할 수 있는지의 여부는 나도 모른다^^.

 

더보기

# 코드 보기

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
#include<stdio.h>
typedef long long ll;
ll solve(ll n,ll m);
ll fpow(ll n,ll k,ll mod){
    ll s=1;
    for(;k;k>>=1){
        if(k&1) s=s*n%mod;
        n=n*n%mod;
    }
    return s;
}
ll phi(ll n){
    ll s=1,i;
    for(i=2;i*i<=n;i+=2){
        if(n%i==0){
            n/=i;
            s*=i-1;
            while(n%i==0){
                n/=i;
                s*=i;
            }
        }
        if(i==2) i--;
    }
    if(n-1) s*=n-1;
    return s;
}
ll gcd(ll a,ll b){
    if(b==0return a;
    return gcd(b,a%b);
}
ll p[50],ch[50],pt;
ll f(ll n,ll v,ll d){
    if(d==pt) return 1;
    if(v==pt){
        ll s=1,i,m=1;
        for(i=0;i<pt;i++){
            if(ch[i]) continue;
            s*=p[i]-1;
            m*=p[i];
        }
        ll g=gcd(n,s);
        if(g>1return -1;
        ll k=phi(s),l,arr[50],ptt=0;
        l=k;
        for(i=2;i*i<=l;i+=2){
            if(l%i==0){
                arr[ptt++]=i;
                while(l%i==0) l/=i;
            }
            if(i==2) i--;
        }
        if(l-1) arr[ptt++]=l;
        for(i=0;i<ptt;i++){
            while(k%arr[i]==0 && fpow(n,k/arr[i],s)==1) k/=arr[i];
        }
        return k;
    }
    ll mi=1,i,t;
    for(i=0;i<2;i++){
        ch[v]=i;
        if(i==0) t=f(n,v+1,d+1);
        else t=f(n,v+1,d);
        if(t==-1return -1;
        mi=mi*t/gcd(mi,t);
    }
    ch[v]=0;
    return mi;
}
ll verify(ll n,ll m,ll s,ll k){
    ll i;
    for(i=2;i*i<=n;i++){
        if(fpow(i,fpow(n,k,s),m)!=i){
            return 0;
        }
    }
    return 1;
}
ll solve(ll n,ll m){
    ll i;
    ll s=1,h=m;
    for(i=2;i*i<=m;i+=2){
        if(m%i==0){
            m/=i;
            s*=i-1;
            p[pt++]=i;
            if(m%i==0return -1;
        }
        if(i==2) i--;
    }
    if(m-1){
        p[pt++]=m;
        s*=m-1;
    }
    ll k=f(n,0,0);
    ll pp[50]={},ppt=0,sub=k;
    for(i=2;i*i<=sub;i+=2){
        if(sub%i==0){
            pp[ppt++]=i;
            while(sub%i==0) sub/=i;
        }
        if(i==2) i--;
    }
    if(sub-1) pp[ppt++]=sub;
    for(i=0;i<ppt;i++){
        while(k%pp[i]==0 && verify(n,h,s,k/pp[i])==1) k/=pp[i];
    }
    return k;
}
int main(){
    ll n;
    scanf("%lld",&n);
    printf("%lld",solve(n,n));
}
cs

# 닫기

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

다이아몬드 달성!!!!!!  (0) 2022.03.05
[BOJ 17105] 골드바흐 트리플  (0) 2022.03.04
[BOJ 13714] 약수의 개수  (0) 2022.02.08
[BOJ 18496] Euclid's Algorithm  (0) 2022.01.16
64일 스트릭!!  (0) 2021.12.20