正文前的一些提示:打
UVA
的题时,输出后一定要有一个空行,否则等待您的,就是一次又一次的WA
。
UVA11426 GCD Extreme(II) \color{green}{\texttt{UVA11426\ \ \ \ GCD Extreme(II)}} UVA11426 GCD Extreme(II)
[Problem] \color{blue}{\texttt{[Problem]}} [Problem]
-
给定一个数 n n n,求:
∑ i = 1 n ∑ j = i + 1 n gcd ( i , j ) \sum\limits_{i=1}^{n} \sum\limits_{j=i+1}^{n} \gcd(i,j) i=1∑nj=i+1∑ngcd(i,j)
-
2 ≤ n ≤ 4 × 1 0 6 2 \leq n \leq 4 \times 10^6 2≤n≤4×106,多组数据,输入以 0 0 0 结束。保证答案在
long long
范围内。
[Solution] \color{blue}{\texttt{[Solution]}} [Solution]
记 f i = ∑ j = 1 i − 1 gcd ( j , i ) f_i = \sum\limits_{j=1}^{i-1} \gcd(j,i) fi=j=1∑i−1gcd(j,i),则答案 S i = ∑ j = 2 n f j S_i=\sum\limits_{j=2}^{n} f_j Si=j=2∑nfj。
求出了所有的 f i ( 2 ≤ i ≤ N ) f_i(2 \leq i \leq N) fi(2≤i≤N) 后( N = 4 × 1 0 6 N = 4 \times 10^6 N=4×106),就可以用 O ( N ) O(N) O(N) 的时间求出所有的 S i ( 2 ≤ i ≤ N ) S_i (2 \leq i \leq N) Si(2≤i≤N)。
现在,让我们考虑如何求出 f i ( 2 ≤ i ≤ N ) f_i(2 \leq i \leq N) fi(2≤i≤N)。
枚举 d d d,代表 gcd ( j , i ) = d \gcd(j,i)=d gcd(j,i)=d,假设这样的 j j j 有 k k k 个,则对答案的贡献为 k × d k \times d k×d。
接下来,考虑如何求出 k k k 的值。显然, i , j i,j i,j 一定满足 d ∣ i , d ∣ j d|i,d|j d∣i,d∣j,且 i d , j d \dfrac{i}{d},\dfrac{j}{d} di,dj 互质。
简单地证明一下:显然 i , j i,j i,j 一定是满足 d ∣ i , d ∣ j d|i,d|j d∣i,d∣j 的,否则 gcd ( i , j ) ≠ d \gcd(i,j) \neq d gcd(i,j)=d。为什么 i d , j d \dfrac{i}{d},\dfrac{j}{d} di,dj 互质呢?
考虑反证法。假设 i d , j d \dfrac{i}{d},\dfrac{j}{d} di,dj 不互质,记其最大公约数为 g g g。那么 g g g 一定也是 i , j i,j i,j 的因子,而且 d × g ∣ i , d × g ∣ j d \times g | i,d \times g | j d×g∣i,d×g∣j,即 d × g d \times g d×g 也是 i , j i,j i,j 的公约数,这与 d d d 是 i , j i,j i,j 的最大公约数矛盾。
有了这个定理,所以一对可行的 ( i , j ) (i,j) (i,j) 一定与一对互质的数 ( i d , j d ) (\dfrac{i}{d}, \dfrac{j}{d}) (di,dj) 一一对应。而因为 i d , j d \dfrac{i}{d},\dfrac{j}{d} di,dj 互质,所以这样的 j d \dfrac{j}{d} dj 一共有 φ ( i d ) \varphi(\dfrac{i}{d}) φ(di) 个,故这样的 j j j 一共有 φ ( i d ) \varphi(\dfrac{i}{d}) φ(di) 个。
所有的 φ ( i ) ( 1 ≤ i ≤ N ) \varphi(i)(1 \leq i \leq N) φ(i)(1≤i≤N) 可以 O ( N ) O(N) O(N) 求出,而枚举 d d d 并计算 f i ( 2 ≤ i ≤ N ) f_i(2 \leq i \leq N) fi(2≤i≤N) 是 O ( N × log N ) O(N\times \log N) O(N×logN) 的,求出 S i ( 2 ≤ i ≤ N ) S_i(2 \leq i \leq N) Si(2≤i≤N) 是 O ( N ) O(N) O(N) 的,输出答案是 O ( 1 ) O(1) O(1) 的。故总的时间复杂度为 O ( N × N + T ) O(N \times N + T) O(N×N+T),其中 T T T 是一共的数据个数。
[code] \color{blue}{\texttt{[code]}} [code]
const int N=4e6+100;
typedef long long ll;
int n,phi[N];ll S[N],f[N];
int prime[N],g[N],tot;//线性筛
inline void get_prime(int N){
tot=0;phi[1]=1;//初始化
for(int i=2;i<=N;i++){
if (!g[i]){//如果i是个素数
phi[i]=i-1;//初始化phi值
g[i]=prime[++tot]=i;
}
for(int j=1;j<=tot;j++){
if (1ll*i*prime[j]>N) break;//剪枝
register int t=i*prime[j];//updata
phi[t]=phi[i]*(prime[j]-(prime[j]<g[i]));
g[t]=prime[j];//记录每个数的最小因子
if (prime[j]==g[i]) break;//算法优化
}
}
}
int main(){
get_prime(4e6);//求出phi值
for(int i=1;i<=(int)4e6;i++)
for(int j=i*2;j<=(int)4e6;j+=i)
f[j]+=1ll*i*phi[j/i];
S[2]=f[2];//注意S[2]应特别赋值f[2]
for(int i=3;i<=(int)4e6;i++)
S[i]=S[i-1]+f[i];//前缀和
while (~scanf("%d",&n)&&n)
printf("%lld\n",S[n]);
return 0;
}