【题解】USB 的数学题

G ( n ) = ∑ i = 1 n i g c d ( i , n ) G(n)=\sum_{i=1}^{n}\frac{i}{gcd(i,n)} G(n)=i=1ngcd(i,n)i 的值,其中 g c d ( i , n ) gcd(i,n) gcd(i,n) i i i n n n 的最大公约数。

输入数据以多组数据给出,数据组数不超过 1 0 5 10^5 105 1 ≤ n ≤ 1 0 6 1≤n≤10^6 1n106


我们先考虑按 i = 1... n i=1...n i=1...n 中的 g c d ( i , n ) gcd(i,n) gcd(i,n) 分类,当 n = 6 n=6 n=6 时,分类如下图:

在这里插入图片描述
因此,对于上式的 G ( n ) G(n) G(n) 也可以写成: G ( n ) = ∑ d ∣ n n d n φ ( d n ) G(n)=\sum_{d|n}^{n}\frac{d}{n}φ(\frac{d}{n}) G(n)=dnnndφ(nd),即 G ( n ) = ∑ d ∣ n n d φ ( d ) G(n)=\sum_{d|n}^{n}dφ(d) G(n)=dnndφ(d)

定理: G ( n ) = ∑ d ∣ n n d φ ( d ) G(n)=\sum_{d|n}^{n}dφ(d) G(n)=dnndφ(d) 为积性函数。

证明:设有正整数 n , m n,m n,m 且互质,所以 n , m n,m n,m 的约数互不相同(不然最大公因数就不是 1 1 1),所以 n m nm nm 的约数个数为 n , m n,m n,m 约数个数的积。因为欧拉函数本身是积性函数,所以可得以下结论:

G ( n ) G ( m ) = ∑ i ∣ n n ∑ j ∣ m m i j φ ( i ) φ ( j ) = ∑ i ∣ n n ∑ j ∣ m m i j φ ( i j ) = G ( n m ) G(n)G(m)=\sum_{i|n}^n\sum_{j|m}^mijφ(i)φ(j)=\sum_{i|n}^n\sum_{j|m}^mijφ(ij)=G(nm) G(n)G(m)=innjmmijφ(i)φ(j)=innjmmijφ(ij)=G(nm)

其中枚举 i , j i,j i,j 后的 i j ij ij 项已经枚举了 n m nm nm 的所有约数,因此 G ( n ) G(n) G(n) 为积性函数。

众所周知,所有积性函数都可以用线性筛法递推得到。对于任意一个质数 x x x 来说, G ( x ) = ( x − 1 ) x + 1 G(x)=(x-1)x+1 G(x)=(x1)x+1,这很容易通过式子证明。

当递推 i ∗ p r i m e [ j ] = k i*prime[j]=k iprime[j]=k 时,若 p r i m e [ j ] prime[j] prime[j] 不是 i i i 的质因子,那么直接有 G ( k ) = G ( i ) G ( p r i m e [ j ] ) G(k)=G(i)G(prime[j]) G(k)=G(i)G(prime[j])

p r i m e [ j ] prime[j] prime[j] i i i 的质因子,分两种情况:

  1. i i i 不是 p r i m e [ j ] prime[j] prime[j] 为底数的幂。
    我们从 i i i 中提取 i i i 最小质因子的指数 m i [ i ] mi[i] mi[i] 和幂 h i g h P o w [ i ] highPow[i] highPow[i]。由线性筛的原理得知, p r i m e [ j ] prime[j] prime[j] 也是 i i i 的最小质因子。令 A = h i g h P o w [ i ] ∗ p r i m e [ j ] , B = i ∗ p r i m e [ j ] / A A=highPow[i]*prime[j],B=i*prime[j]/A A=highPow[i]prime[j],B=iprime[j]/A,那么很容易递推 G ( i ∗ p r i m e [ j ] ) = G ( A ) G ( B ) G(i*prime[j])=G(A)G(B) G(iprime[j])=G(A)G(B)

  2. i i i p r i m e [ j ] prime[j] prime[j] 为底数的幂。
    若用上述方法,会得出 A = i ∗ p r i m e [ j ] , B = 1 A=i*prime[j],B=1 A=iprime[j],B=1,无法递推。设 k = i ∗ p r i m e [ j ] k=i*prime[j] k=iprime[j],利用之前的式子,很容易可知 G ( k ) = ∑ p = 0 m i [ k ] p r i m e [ j ] p φ ( p r i m e [ j ] p ) G(k)=\sum_{p=0}^{mi[k]}prime[j]^pφ(prime[j]^p) G(k)=p=0mi[k]prime[j]pφ(prime[j]p)。由欧拉函数的计算公式可知, φ ( p r i m e [ j ] p ) = p r i m e [ j ] p ( 1 − 1 p r i m e [ j ] ) φ(prime[j]^p)=prime[j]^p(1-\frac{1}{prime[j]}) φ(prime[j]p)=prime[j]p(1prime[j]1)。因此,上述 G ( k ) G(k) G(k) 的公式可以用暴力实现。

其中 h i g h P o w [ ] highPow[] highPow[] m i [ ] mi[] mi[] 都可以通过线性筛来实现。如果是这样,我们就可以不用计算欧拉函数了。


#include<bits/stdc++.h>
#define int long long
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
int n,t,x,prime[10000010],m,ans,g[10000010],highPow[10000010],mi[10000010],w[2][10000010];
bool b[10000010];
signed main()
{
	scanf("%lld",&t);
	n=10000000;
	for(int i=2;i<=n;i++)
	{
		if(!b[i]) //没有被筛选过,说明 i 是质数
		{
			g[i]=i*(i-1)+1;
			highPow[i]=i;
			mi[i]=1;
			prime[++m]=i;
		}
		for(int j=1;j<=m&&i*prime[j]<=n;j++)
		{
			int x=i*prime[j]; //k=x=i*prime[j]
			b[x]=true; //筛选质数
			if(i%prime[j]) //i 和 prime[j] 互质
			{
				int A=i,B=prime[j];
				g[x]=g[A]*g[B];
				highPow[x]=B;
				mi[x]=1;
			}
			else
			{
				highPow[x]=highPow[i]*prime[j];
				mi[x]=mi[i]+1;
				int A=highPow[x];
				int B=i*prime[j]/A;
				if(B==1) //分情况,如果 i 是 prime[j] 的幂
				{
					w[0][0]=w[1][0]=1;
					w[0][1]=prime[j];
					w[1][1]=prime[j]-1;
					for(int k=2;k<=mi[x];k++)
					{
						w[0][k]=w[0][k-1]*prime[j];
						w[1][k]=w[1][k-1]*prime[j];
					}
					for(int k=0;k<=mi[x];k++)
					{
						g[x]+=w[0][k]*w[1][k];
					}
				}
				else
				{
					g[x]=g[A]*g[B];
				}
				break; 
			}
		}
	}
	while(t--)
	{
		scanf("%lld",&x);
		if(x-1)printf("%lld\n",g[x]); //if(x-1)就是x不等于1
		else printf("1\n");//特判 1 的情况
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值