BZOJ[SPOJ5971]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 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 <= T <= 300000
1 <= n <= 1000000

题解:

题意即求∑LCM(i,n)(1<=i<=n)。

枚举lcm,统计对答案的贡献。

原本我采用的方法是容斥,求出n的因数表后,由大到小枚举lcm[i],并把更小的lcm[j]的贡献减去相应的值。

复杂度还可以,但是常数非常大,在BZ上过不了。

有一个常数更小的方法:枚举lcm后,我们需要知道1~n div lcm-1中所有与n div lcm互质的数的和。

设m=n div lcm。若x与m互质,则m-x与m互质,即与m互质的数成对出现,所以与m互质的数的和为m*φ(m)div 2。(m<=2时依旧成立)

线性筛预处理出欧拉函数,就可以快速求值了。

代码:

TLE的容斥(P++注意):

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define begin {
 4 #define end }
 5 #define while while(
 6 #define if if(
 7 #define do )
 8 #define then )
 9 #define for for(
10 #define fillchar(a,b,c) memset(a,c,b)
11 #define writeln printf("\n")
12 #define write printf
13 #define readln readl()
14 #define inc(a) a++
15 #define dec(a) a--
16 #define exit(a) return a
17 #define mod %
18 #define div /
19 #define shl <<
20 #define shr >>
21 #define extended long double
22 #define longint int
23 #define integer short
24 #define int64 long long
25 template<typename T> inline void read(T& a)
26 begin
27   T x=0,f=1; char ch=getchar();
28   while(ch<‘0‘)or(ch>‘9‘)do
29   begin
30     if ch==‘-‘ then f=-1; ch=getchar();
31   end
32   while(ch>=‘0‘)and(ch<=‘9‘)do
33   begin
34     x=x*10+ch-‘0‘; ch=getchar();
35   end
36   a=x*f;
37 end
38 inline void readl()
39 begin
40   char ch; ch=getchar();
41   while ch!=‘\n‘ do ch=getchar();
42 end
43 int64 i,t,ii,j,n,m,x,a[3002],b[1000002],ans;
44 int main()
45 begin
46   read(t);
47   for ii=1;ii<=t;ii++ do
48   begin
49     read(x); j=sqrt(x); n=0; m=0; ans=0;
50     for i=1;i<=j;i++ do
51     begin
52       if x mod i==0 then
53       begin
54         inc(n); a[n]=i;
55         if x div i>i then begin inc(m); a[2002-m]=x div i; end;
56       end
57     end
58     for i=n+1;i<=n+m;i++ do a[i]=a[2002-(m-(i-n)+1)];
59     n=n+m;
60     for i=1;i<=n;i++ do b[a[i]]=0;
61     for i=n;i>=1;i-- do
62     begin
63       b[a[i]]=b[a[i]]+(1+x div a[i])*(x div a[i])div 2;
64       ans=ans+b[a[i]]*x;
65       j=1;
66       while a[j]*a[j]<=a[i] do
67       begin
68         if j>n then break;
69         if a[i] mod a[j]==0 then
70         begin
71           b[a[j]]=b[a[j]]-(a[i] div a[j])*b[a[i]];
72           if(a[j]*a[j]<a[i])and(a[j]>1)then
73           b[a[i] div a[j]]=b[a[i] div a[j]]-a[j]*b[a[i]];
74         end
75         inc(j);
76       end
77     end
78     write("%lld",ans); writeln;
79   end
80 end

标程(P++注意):

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define begin {
 4 #define end }
 5 #define while while(
 6 #define if if(
 7 #define do )
 8 #define then )
 9 #define for for(
10 #define fillchar(a,b,c) memset(a,c,b)
11 #define writeln printf("\n")
12 #define write printf
13 #define readln readl()
14 #define inc(a) a++
15 #define dec(a) a--
16 #define exit(a) return a
17 #define mod %
18 #define div /
19 #define shl <<
20 #define shr >>
21 #define extended long double
22 #define longint int
23 #define integer short
24 #define int64 long long
25 template<typename T> inline void read(T& a)
26 begin
27   T x=0,f=1; char ch=getchar();
28   while(ch<‘0‘)or(ch>‘9‘)do
29   begin
30     if ch==‘-‘ then f=-1; ch=getchar();
31   end
32   while(ch>=‘0‘)and(ch<=‘9‘)do
33   begin
34     x=x*10+ch-‘0‘; ch=getchar();
35   end
36   a=x*f;
37 end
38 inline void readl()
39 begin
40   char ch; ch=getchar();
41   while ch!=‘\n‘ do ch=getchar();
42 end
43 longint p[1000100],vis[1000100],ph[1000100],pcnt=0,T,n;
44 void init_p()
45 begin
46   ph[1]=1; ph[2]=1;
47   int64 temp;
48   for int i=2;i<1000100;i++ do
49   begin
50     if not vis[i] then
51     begin
52       p[pcnt]=i; ph[i]=i-1; inc(pcnt);
53     end
54     for int j=0;j<pcnt&&(temp=(int64)p[j]*i)<1000100;j++ do
55     begin
56       vis[temp]=1;
57       if i mod p[j]==0 then begin ph[temp]=ph[i]*p[j]; break; end
58       else ph[temp]=ph[i]*(p[j]-1);
59     end
60   end
61 end
62 int64 solve(int n)
63 begin
64   int64 ans=0ll;
65   longint half=(int)(sqrt(n)+0.01);
66   if half*half==n then begin ans+=1ll*ph[half]*half/2; dec(half); end
67   inc(ans); ans+=1ll*ph[n]*n/2;
68   for int i=2;i<=half;i++ do
69   if n mod i==0 then
70   begin
71     ans+=1ll*ph[i]*i/2;
72     ans+=1ll*ph[n/i]*n/i/2;
73   end
74   exit(ans*n);
75 }
76 int main()
77 begin
78   read(T); init_p();
79   for int i=1;i<=T;i++ do
80   begin read(n); write("%lld",solve(n)); writeln; end
81   return 0;
82 end

时间: 2024-11-10 01:22:01

BZOJ[SPOJ5971]LCMSum的相关文章

[BZOJ2226][SPOJ5971]LCMSum(莫比乌斯反演)

2226: [Spoj 5971] LCMSum Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1949  Solved: 852[Submit][Status][Discuss] 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 in

[欧拉函数] Bzoj P2226 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. 题解 代码 1 #include <cstdio> 2 #include <iostream> 3 #define N 1000010 4 #define ll long long 5

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  ----------------------------------------------

「SPOJ5971」 LCMSUM - 数论数学

题目描述 求 \(\sum_{i=1}^nlcm(i,n)\) \(T\) 组数据 \(1\le T\le 300000\) \(1\le n\le 1000000\) 链接 bzoj 2226 luogu SP5971 题解 算法1(暴力) 直接暴力枚举 \(i\) ,计算 \(lcm\) 时间复杂度 \(O(Tnlogn)\) 算法2 (数论) 先不管最后一个,就变成了这个: \[ \sum_{i=1}^{n-1}lcm(i,n) \] 将 \(lcm\) 转化为 \(gcd\): \[ A

BZOJ 2226: [Spoj 5971] LCMSum

Description 求\(\sum_{i=1}^n[i,n],n\leqslant 10^6,T\leqslant 3\times 10^5\) Solution 数论.. \(\sum_{i=1}^n[i,n]\) \(=n\sum_{i=1}^n\frac{i}{(i,n)}\) \(=n\sum_{d|n}\sum_{i=1}^{\frac{n}{d}}[(i,\frac{n}{d})=1]i\) 后面这个其实可以直接算出来 \(\sum_{i=1}^n[(i,n)=1]i=\sum_

BZOJ 1363 最小公倍数之和

Description 求\(\sum_{i=1}^n[i,n],n\leqslant 10^9,T\leqslant 5\times 10^4\) Solution 数论+欧拉函数... 破题有毒... 推导和BZOJ 2226: [Spoj 5971] LCMSum一样... 但是需要枚举所有约数,同时统计一下\(\varphi\)... Code #include <bits/stdc++.h> using namespace std; typedef long long ll; con

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比