【CF#235E】Number Challenge

  • 本文为博主原创,未经许可不得转载

首先有一个结论:

证明略,接下来开始推式子:

配合记忆化预处理GCD,时间复杂度:$O(n^2 log 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
#include<bits/stdc++.h>
#define FILE "read"
#define MAXN 5050
#define cadd(a,b) a=add(a,b)
#define csub(a,b) a=sub(a,b)
#define cmul(a,b) a=mul(a,b)
using namespace std;
const int mod=1073741824;
int A,B,C,N,cnt,ans,check[MAXN],prime[MAXN],mu[MAXN],GCD[MAXN][MAXN];
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int sub(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return 1LL*a*b%mod;}
inline int gcd(int a,int b){
if(GCD[a][b]) return GCD[a][b];
else return !b?a:gcd(b,a%b);
}
void Init(){
mu[1]=1; N=5000;
for(int i=2;i<=N;++i){
if(!check[i]) prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&prime[j]*i<=N;++j){
check[prime[j]*i]=1;
if(i%prime[j]==0) {mu[prime[j]*i]=0; break;}
else mu[prime[j]*i]=-mu[i];
}
}
for(int i=1;i<=N;++i)for(int j=i;j<=N;++j)
GCD[i][j]=GCD[j][i]=gcd(i,j);
}
int calc(int A,int d,int k){
int ret=0;
for(int i=1;i<=(A/d);++i)
if(GCD[d*i][k]==1) cadd(ret,A/(d*i));
return ret;
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
scanf("%d%d%d",&A,&B,&C); Init();
for(int k=1;k<=C;++k){
int ret=0;
for(int d=1;d<=min(A,B);++d)if(mu[d])
cadd(ret,mul(mu[d],mul(calc(A,d,k),calc(B,d,k))));
cmul(ret,C/k); cadd(ans,ret);
}
printf("%d\n",ans);
printf("%d\n",clock());
return 0;
}
文章目录
,