2020.06.13日常总结

正文前的一些提示:打 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=1nj=i+1ngcd(i,j)

  • 2 ≤ n ≤ 4 × 1 0 6 2 \leq n \leq 4 \times 10^6 2n4×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=1i1gcd(j,i),则答案 S i = ∑ j = 2 n f j S_i=\sum\limits_{j=2}^{n} f_j Si=j=2nfj

求出了所有的 f i ( 2 ≤ i ≤ N ) f_i(2 \leq i \leq N) fi(2iN) 后( 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(2iN)

现在,让我们考虑如何求出 f i ( 2 ≤ i ≤ N ) f_i(2 \leq i \leq N) fi(2iN)

枚举 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 di,dj,且 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 di,dj 的,否则 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×gi,d×gj,即 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)(1iN) 可以 O ( N ) O(N) O(N) 求出,而枚举 d d d 并计算 f i ( 2 ≤ i ≤ N ) f_i(2 \leq i \leq N) fi(2iN) 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(2iN) 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值