spoj LCMSUM sigma(lcm(i,n));

Problem code: LCMSUM

Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + 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.

Example

Sample Input :
3
1
2
5

Sample Output :
1
4
55

Constraints

1 <= T <= 300000
1 <= n <= 1000000

题意:sigma(lcm(i,n)) ; 1<=i<=n

思路:题意倒是很简单,有类似的题目sigma(gcd(i,n)) ;1<=i<=n;

    一看就是果然是同类型的。

gcd(i,n)的题目 http://www.cnblogs.com/tom987690183/p/3247439.html

这个是求lcm()最小公倍数.

同样的思路,我们枚举gcd() = d 则在[ 1 , n ]中与n最大公约数为d的值有euler(n/d)个.

这些数的和为euler(n/d)*n/2;  我们知道lcm = x*n/(gcd(x,n)) = > x*n/d ;

因为与n gcd() = d的数字为x1,x2,x3....

根据lcm = x*n/(gcd(x,n)) 可以得到 (n/d)*(x1+x2+x3...) => [euler(n/d)*n/2]*(n*d);

这里需要注意的是当gcd(i,n) = n的时候,用euler(n)*n/2算的时候是不对的,就特判吧。

这样的思路,我们就可以试一下打欧拉表opl[ ],需要时间o(N);

然后对于n,要用sqrt(n)的时间。

T*sqrt(n)+o(N) = 3^8+10^6.果断超时。以为能ac,吼吼。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<cstdlib>
 5 using namespace std;
 6 typedef long long LL;
 7
 8 const int maxn = 1e6+3;
 9 int opl[maxn];
10 void init()
11 {
12     for(int i=1;i<maxn;i++) opl[i] = i;
13     for(int i=2;i<maxn;i++)
14     {
15         if(opl[i]==i) opl[i] = i-1;
16         else continue;
17         for(int j=i+i;j<maxn;j=j+i)
18             opl[j] = opl[j]/i*(i-1);
19     }
20 }
21 int main()
22 {
23     int T;
24     LL n;
25     init();
26     scanf("%d",&T);
27     while(T--)
28     {
29         scanf("%lld",&n);
30         LL sum = 0;
31         for(LL i=1;i*i<=n;i++)
32         {
33             if(n%i==0)
34             {
35                 if(i!=n)
36                 sum = sum + (n/i)*(opl[n/i]*n/2);
37                 LL tmp = n/i;
38                 if(tmp!=i && tmp!=n)
39                     sum = sum + i*(opl[i]*n/2);
40             }
41         }
42         printf("%lld\n",sum+n);
43     }
44     return 0;
45 }

这样的话,是不行了。

原始相当于

也就能转化为(easy)

这样的话,我们就能单独的求出euler(a)*a/2;然后用它来筛选g[n]的值。

(x|n的意思代表 n是x的倍数)

我们想到在第一种方法里,我们用sqrt(n)来求它的因子的方法。

同理,逆向一下就好。

这样我们只需要o(N) 的时间对g[]进行筛选。总的预处理时间

3*o(N) = > 3*10^6;

完毕。

需要注意的是,我们没有把gcd() = n的情况包含进去,所以最后要+n。

代码:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<cstdlib>
 5 using namespace std;
 6 typedef long long LL;
 7
 8 const int maxn = 1e6+3;
 9 LL opl[maxn];
10 LL g[maxn];
11 void init()
12 {
13     for(int i=1;i<maxn;i++) opl[i] = i;
14     //这种方法筛选素数,不用和以前一样要先刷素数,还开num[];
15     for(int i=2;i<maxn;i++)
16     {
17         if(opl[i]==i)
18             opl[i] = i-1;
19         else continue;
20         for(int j=i+i;j<maxn;j=j+i)
21             opl[j] = opl[j]/i*(i-1);
22     }
23     for(int i=2;i<maxn;i++){
24         opl[i] = opl[i]*i/2;
25         g[i] = opl[i];
26     }
27     for(long long i=2;i<=1000;i++) //这里的i 不能用int,肯定会超int的
28     {
29         for(long long j=i*i,k=i;j<maxn;j=j+i,k++)
30         if(i!=k) //不重复
31             g[j] = g[j] + opl[i]+opl[k];
32         else g[j] = g[j] + opl[i];
33     }
34 }
35 int main()
36 {
37     init();
38     int T;
39     LL n;
40     scanf("%d",&T);
41     while(T--)
42     {
43         scanf("%lld",&n);
44         printf("%lld\n",g[n]*n+n);
45     }
46     return 0;
47 }
时间: 2024-10-12 21:42:11

spoj LCMSUM sigma(lcm(i,n));的相关文章

SPOJ LCMSUM - LCM Sum

题意是求: $\sum_{i = 1}^{n}lcm(i, n)$ $= \sum_{i = 1}^{n}\frac{ni}{gcd(i, n)}$ $= n\sum_{i = 1}^{n}\frac{i}{gcd(i, n)}$ $= n\sum_{d|n}\sum_{i = 1}^{n}d*[gcd(i, n)==d]$ $= n\sum_{d|n}\sum_{i = 1}^{\frac{n}{d}}i*[gcd(i, \frac{n}{d})==1]$ $= n\sum_{d|n}\sum

数论十题

数论十题 Problem Zero:[neerc2011]Gcd guessing game 现在有一个数x,1 ≤ x≤ n,告诉你n,每次你可以猜一个数y,如果x==y则结束,否则返回gcd(x,y),问最少只要几次就可以保证猜出答案. 本题纯属娱乐.仅仅是一个GCD的游戏,跑题了. 因为本题要求最坏情况,我们直观地猜想就是每次返回都是1.由于答案有可能是质数,而判定一个数,必须要把含有这个质因子的数问一遍.于是,我们引出这样一个思路,将所有1-n的质数分组,每组的积<=n,答案就是组数.

(转载)有关反演和gcd

tips : 积性函数 F (n) = Π F (piai ) 若F (n), G (n)是积性函数则 F (n) * G (n) Σd | n F (n) 是积性函数 n = Σd | n  φ (d) 1 = Σd | n  μ (d) Σgcd (i, n) = 1 i = n * φ (n) / 2 Problem1 F (n) = Σ1<= i <= n gcd(i, n), n <= 1000000 Sol 枚举结果 F (n) = Σd | n d * Σgcd (i, n

51Nod 最大公约数之和V1,V2,V3;最小公倍数之和V1,V2,V3

1040 最大公约数之和 给出一个n,求1-n这n个数,同n的最大公约数的和.比如:n = 6 1,2,3,4,5,6 同6的最大公约数分别为1,2,3,2,1,6,加在一起 = 15 输入 1个数N(N <= 10^9) 输出 公约数之和 输入样例 6 输出样例 15 题解 \[ \sum_{i=1}^n\gcd(i,n)=\sum_{d|n}d\varphi(n) \] 暴力搞就行了. 1188 最大公约数之和 V2 给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和. 相当于计

P1377发奖金

Bsny最近公司运作不佳,本年度利润才m元,但员工的奖金还是要发的,公司有n个员工,怎么发奖金这个完全由老板Bsny自己决定.Bsny想要么把这m元全发了,激励一下员工,但具体怎么分配方案有很多.比如m=1, n=2, 那么可以员工1发1元,员工2发0元:也可以员工1发0元,员工2发1元,有两种方案. 但其实,Bsny还是有点吝啬的,他想这m元不一定全部作为奖金,可以部分留给自己,这样的话,发奖金的方案数就更多了.还是以m=1, n=2为例子: 方案1:员工1发1元,员工2发0元 方案2:员工1

【莫比乌斯反演】BZOJ2154 Crash的数字表格

Description 求sigma lcm(x,y),x<=n,y<=m.n,m<=1e7. Solution lcm没有什么直接做的好方法,用lcm=x*y/gcd转成gcd来做 就是要求sigma d*f(x/d,y/d) f(x,y)为x和y以内gcd正好为1的对数 F为所有对数,于是有F(x,y)=x*(x+1)/2*y*(y+1)/2 f(x,y)=sigma (1<=i<=x) i*i*mu(i)*F(x/i,y/i) f用莫比乌斯反演解决,这两个式子都套上分块

bzoj 2693: jzptab 线性筛积性函数

2693: jzptab Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 444  Solved: 174[Submit][Status][Discuss] Description Input 一个正整数T表示数据组数 接下来T行 每行两个正整数 表示N.M Output T行 每行一个整数 表示第i组数据的结果 Sample Input 1 4 5 Sample Output 122 HINT T <= 10000 N, M<=10000000

BZOJ 2226: [Spoj 5971] LCMSum( 数论 )

∑lcm(i,n) = ∑ i*n/(i,n) = ∑d|n∑(x,n)=d x*n/d = ∑d|n∑(t,n/d)=1t*n = n∑d|nf(d). f(d)表示1~d中与d互质的数的和, 即f(d) = d*φ(d)/2(d>=2). 然后O(n)筛φ, 每次询问暴力算即可...最大是100w,sqrt(100w)=1000内的质数是168个, 所以复杂度是O(n + T*168), 可以AC  ----------------------------------------------

【BZOJ2226】[Spoj 5971] LCMSum 莫比乌斯反演(欧拉函数?)

[BZOJ2226][Spoj 5971] LCMSum Description Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + 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 n