2022. 2. 8. 17:46ㆍPS/백준
위 문제에서 구하고자 하는 것은 다음과 같다.
a∑i=1b∑j=1c∑k=1τ(ijk)
필요한 이론을 증명하고 문제를 해결하자.
Theorm 1. τ(ij)=∑x|i∑y|j[x⊥y]
Lemma 1.
n=k∏i=0paiit (pi∤t)
일 때 다음은 n의 약수 중 pi들의 배수의 개수이다.
k∏i=0aiτ(t)
i=pas(p∤s), j=pbt(p∤t)라 가정하자.
τ(ij)=(a+b+1)τ(st)
s,t가 서로소가 아니므로 위 과정을 반복해주자.
τ(ij)=(a0+b0+1)(ai+bi+1)τ(s1t1)=k∏i=0(ai+bi+1)τ(sk)τ(tk)
gcd(sk,tk)=1이다. 마찬가지 방법으로 τ(i),τ(j)를 전개하자.
τ(i)=k∏i=0(ai+1) τ(sk)
τ(j)=k∏i=0(bi+1) τ(tk)
τ(i)τ(j)=k∏i=0(aibi+ai+bi+1) τ(sk)τ(tk)
τ(ij)는 τ(i)τ(j)에서 aibi라는 항이 빠진 형태이다. 이것은 i,j의 약수를 각각 x,y라 했을 때 x,y를 동시에 나누는 소수 p가 존재하는 x,y 쌍의 개수를 약수의 곱에서 제외시켜야 함을 의미한다. 즉, 다음과 같이 쓸 수 있다.
보충 설명(클릭하세요)
aiτ(sk)biτ(tk)이고 이 항이 사라진 것이므로 Lemma 1에 의해 동시에 pi으로 나누어 떨어지는 약수가 제외됨을 확인할 수 있다.
∑x|i∑y|j1−∑x|i∑y|j[gcd(x,y)>1]
∑x|i∑y|j[gcd(x,y)=1]=∑x|i∑y|j[x⊥y]
위 과정은 i,j 2개인 경우를 진행했다. 3개인 경우는 위의 경우에서 i 또는 j를 더 쪼개면 된다.
τ(ijk)=∑x|i∑y|j∑z|k[x⊥y][y⊥z][z⊥x]
가장 처음의 식을 다음과 같이 변형한다.
a∑i=1b∑j=1c∑k=1∑x|i∑y|j∑z|k[x⊥y][y⊥z][z⊥x]
순서를 바꾼다.
a∑x=1b∑y=1c∑z=1[a/x][b/y][c/z][x⊥y][y⊥z][z⊥x]
a∑x=1[a/x]b∑y=1[b/y][x⊥y]c∑z=1[c/z][x⊥z]∑d|y,zμ(d)
y=dp,z=dq라 두자.
a∑x=1[a/x]min(b,c)∑d=1μ(d)[x⊥d][b/d]∑p=1[b/dp][x⊥p][c/d]∑q=1[c/dq][x⊥q]
W(s,t)=s∑i=1[s/i][t⊥i]
라 정의한다. 다시 표현하면
a∑x=1[a/x]min(b,c)∑d=1μ(d)[x⊥d]W([b/d],x)W([c/d],x)
[x⊥y]의 누적합을 전처리 한다면 W는 O(√s)안에 계산할 수 있다. μ(y)[x⊥y]의 누적합을 전처리 한다면 ∑min(b,c)d=1를 O(√n)으로 계산할 수 있다. 따라서 전체 시간 복잡도는 O(n2)이다.
이것을 구현한 코드이다.
코드 보기
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
|
#include<stdio.h>
typedef long long ll;
#define sz 2001
ll cop[sz][sz];
ll pre_cop[sz][sz];
ll mu_cop[sz][sz];
ll mu[sz];
ll mod=1<<30;
ll sp[sz];
ll prime[sz],pt;
ll pre_bc[sz];
ll min(ll a,ll b){
return a>b?b:a;
}
ll W(ll s,ll t){
ll i,j,sum=0;
for(i=1;i<=s;i=j+1){
j=s/(s/i);
sum+=s/i*(pre_cop[t][j]-pre_cop[t][i-1])%mod;
sum%=mod;
}
return sum;
}
int main(){
ll i,j,k;
for(i=1;i<sz;i++){
for(j=1;j<sz;j++) cop[i][j]=1;
}
for(i=2;i<sz;i++){
ll h=i;
for(j=2;j*j<=h;j++){
if(h%j==0){
for(k=j;k<sz;k+=j){
cop[i][k]=0;
}
while(h%j==0) h/=j;
}
}
if(h-1){
for(j=h;j<sz;j+=h) cop[i][j]=0;
}
for(j=1;j<sz;j++) pre_cop[i][j]=cop[i][j]+pre_cop[i][j-1];
}
for(i=1;i<sz;i++){
pre_cop[1][i]=cop[1][i]+pre_cop[1][i-1];
}
mu[1]=1;
for(i=2;i<sz;i++){
if(!sp[i]){
prime[pt++]=i;
mu[i]=-1;
}
for(j=0;j<pt;j++){
if(i*prime[j]>sz) break;
sp[i*prime[j]]=1;
if(i%prime[j]==0) break;
mu[i*prime[j]]=mu[i]*mu[prime[j]];
}
}
for(i=1;i<sz;i++){
for(j=1;j<sz;j++){
mu_cop[i][j]=mu[j]*cop[i][j]+mu_cop[i][j-1];
}
}
ll a,b,c,sum=0;
scanf("%lld %lld %lld",&a,&b,&c);
for(i=1;i<=min(b,c);i=pre_bc[i]+1){
pre_bc[i]=min(b/(b/i),c/(c/i));
}
for(i=1;i<=a;i++){
ll s=0;
for(j=1;j<=min(b,c);j=k+1){
k=pre_bc[j];
s+=W(b/j,i)*W(c/j,i)%mod*(mu_cop[i][k]-mu_cop[i][j-1])%mod;
s%=mod;
}
sum=(sum+s*(a/i)%mod)%mod;
}
printf("%lld",sum);
}
|
cs |
'PS > 백준' 카테고리의 다른 글
[BOJ 17105] 골드바흐 트리플 (0) | 2022.03.04 |
---|---|
[BOJ 16808] Identity Function (0) | 2022.02.14 |
[BOJ 18496] Euclid's Algorithm (0) | 2022.01.16 |
64일 스트릭!! (0) | 2021.12.20 |
[BOJ 10438] 페리 수열의 합 (0) | 2021.11.20 |