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;
    }
    
  • 相关阅读:
    最优装载(二分答案)
    最小生成树
    hibernate映射实体类查询时数据库空字段赋值给实体类报错的问题
    'hibernate.dialect' must be set when no Connection avalable
    简单了解一下oracle中的显示游标和存储过程
    oracle中的预定异常和自定义异常
    PL/sql中如何声明变量,常量,控制语句及for,loop,while和顺序控制的使用
    简单了解,使用oracle中的索引,表分区
    oracle中序列,同义词的创建
    数据库权限管理
  • 原文地址:https://www.cnblogs.com/mmlz/p/4394723.html
Copyright © 2011-2022 走看看