zoukankan      html  css  js  c++  java
  • BZOJ 2226 LCMSum

    Description

    Given (n), calculate the sum (LCM(1,n) + LCM(2,n) + cdots + LCM(n,n)), where (LCM(i,n)) denotes the Least Common Multiple of the integers (i) and (n).

    Input

    The first line contains (T) the number of test cases. Each of the next (T) lines contain an integer (n).

    Output

    Output (T) lines, one for each test case, containing the required sum.

    Sample Input

    3
    1
    2
    5

    Sample Output

    1
    4
    55

    HINT

    (1 le T le 300000)
    (1 le n le 1000000)

    题目求$$sum_{i=1}^{n}LCM(i,n)$$
    根据(LCM)的公式,即$$sum_{i=1}^{n}frac{i imes n}{GCD(i,n)}$$
    我们枚举(GCD)——(g),即$$sum_{g=1}^{n}[g mid n]n sum_{i=1}^{n}i[GCD(i,n)=g]$$
    化简一下,转而求$$sum_{g=1}^{n}[g mid n]n sum_{i=1}^{n}i[GCD(frac{i}{g},frac{n}{g})=1]$$
    变化一下(i)的范围:$$sum_{g=1}^{n}[g mid n]n sum_{i=1}^{frac{n}{g}}i[GCD(i,frac{n}{g})=1]$$
    (sum_{i=1}^{frac{n}{g}}i[GCD(i,frac{n}{g})=1])(frac{n}{g})内与之互质的数的和,这个有个公式:$$sum_{i=1}^{n}i[GCD(n,i)=1]= frac{phi(n) imes n}{2}$$
    如何证明,假设某个数(a)(n)互质,那么(n-a)一定也与(n)互质,这样的数一共有(phi(n))个,于是得证,但在(n=1)是要特判,于是这个式子就出来了。$$sum_{i=1}{n}LCM(i,n)=sum_{g=1}{n}[g mid n]n frac{phi(frac{n}{g}) imes frac{n}{g} }{2}$$

    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    typedef long long ll;
    #define maxn (1000010)
    bool exist[maxn]; int n,phi[maxn],prime[maxn],tot;
    
    inline void ready()
    {
    	phi[1] = 1;
    	for (int i = 2;i < maxn;++i)
    	{
    		if (!exist[i]) phi[i] = i-1,prime[++tot] = i;
    		for (int j = 1;j <= tot;++j)
    		{
    			if (i*prime[j] >= maxn) break;
    			exist[i*prime[j]] = true;
    			if (i % prime[j] == 0) { phi[i*prime[j]] = phi[i]*prime[j]; break; }
    			else phi[i*prime[j]] = phi[i]*phi[prime[j]];
    		}
    	}
    }
    inline ll calc(int g)
    {
    	if (g == 1) return 1;
    	return ((ll)phi[g]*(ll)g>>1);
    }
    
    int main()
    {
    	freopen("2226.in","r",stdin);
    	freopen("2226.out","w",stdout);
    	ready();
    	int T; scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%d",&n);
    		ll ans = 0;
    		for (int g = 1;g * g <= n;++g)
    			if (n % g == 0)
    			{
    				ans += (ll)n*calc(n / g);
    				if (g * g != n) ans += (ll)n*calc(g);
    			}
    		printf("%lld
    ",ans);
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    《std测试》
    《关于cmp返回值的理解》
    《武汉大学2020年新生程序设计竞赛》
    《多校打卡 * 2018 Multi-University Training Contest 1》
    《牛客练习赛28-B》
    python使用sqlite示例
    python 使用mysql示例
    使用virtualenv为应用提供了隔离的Python运行环境
    生成字母验证码图片
    模拟微博登录
  • 原文地址:https://www.cnblogs.com/mmlz/p/4394723.html
Copyright © 2011-2022 走看看