BZOJ2226:[SPOJ5971]LCMSum
Description
Input
Output
Sample Input
1
2
5
Sample Output
4
55
HINT
1 <= T <= 300000
1 <= n <= 1000000
题解:
题意即求∑LCM(i,n)(1<=i<=n)。
枚举gcd,统计对答案的贡献。
原本我采用的方法是容斥,求出n的因数表后,由大到小枚举gcd[i],并把更小的gcd[j]的贡献减去相应的值。
复杂度还可以,但是常数非常大,在BZ上过不了。
有一个常数更小的方法:枚举gcd后,我们需要知道1~n div gcd-1中所有与n div gcd互质的数的和。
设m=n div gcd。若x与m互质,则m-x与m互质,即与m互质的数成对出现,所以与m互质的数的和为m*φ(m)div 2。(m<=2时依旧成立)
线性筛预处理出欧拉函数,就可以快速求值了。
代码:
TLE的容斥(P++注意):
#include <bits/stdc++.h>
using namespace std;
#define begin {
#define end }
#define while while(
#define if if(
#define do )
#define then )
#define for for(
#define fillchar(a,b,c) memset(a,c,b)
#define writeln printf("\n")
#define write printf
#define readln readl()
#define inc(a) a++
#define dec(a) a--
#define exit(a) return a
#define mod %
#define div /
#define shl <<
#define shr >>
#define extended long double
#define longint int
#define integer short
#define int64 long long
template<typename T> inline void read(T& a)
begin
T x=,f=; char ch=getchar();
while(ch<'')or(ch>'')do
begin
if ch=='-' then f=-; ch=getchar();
end
while(ch>='')and(ch<='')do
begin
x=x*+ch-''; ch=getchar();
end
a=x*f;
end
inline void readl()
begin
char ch; ch=getchar();
while ch!='\n' do ch=getchar();
end
int64 i,t,ii,j,n,m,x,a[],b[],ans;
int main()
begin
read(t);
for ii=;ii<=t;ii++ do
begin
read(x); j=sqrt(x); n=; m=; ans=;
for i=;i<=j;i++ do
begin
if x mod i== then
begin
inc(n); a[n]=i;
if x div i>i then begin inc(m); a[-m]=x div i; end;
end
end
for i=n+;i<=n+m;i++ do a[i]=a[-(m-(i-n)+)];
n=n+m;
for i=;i<=n;i++ do b[a[i]]=;
for i=n;i>=;i-- do
begin
b[a[i]]=b[a[i]]+(+x div a[i])*(x div a[i])div ;
ans=ans+b[a[i]]*x;
j=;
while a[j]*a[j]<=a[i] do
begin
if j>n then break;
if a[i] mod a[j]== then
begin
b[a[j]]=b[a[j]]-(a[i] div a[j])*b[a[i]];
if(a[j]*a[j]<a[i])and(a[j]>)then
b[a[i] div a[j]]=b[a[i] div a[j]]-a[j]*b[a[i]];
end
inc(j);
end
end
write("%lld",ans); writeln;
end
end
标程(P++注意):
#include <bits/stdc++.h>
using namespace std;
#define begin {
#define end }
#define while while(
#define if if(
#define do )
#define then )
#define for for(
#define fillchar(a,b,c) memset(a,c,b)
#define writeln printf("\n")
#define write printf
#define readln readl()
#define inc(a) a++
#define dec(a) a--
#define exit(a) return a
#define mod %
#define div /
#define shl <<
#define shr >>
#define extended long double
#define longint int
#define integer short
#define int64 long long
template<typename T> inline void read(T& a)
begin
T x=,f=; char ch=getchar();
while(ch<'')or(ch>'')do
begin
if ch=='-' then f=-; ch=getchar();
end
while(ch>='')and(ch<='')do
begin
x=x*+ch-''; ch=getchar();
end
a=x*f;
end
inline void readl()
begin
char ch; ch=getchar();
while ch!='\n' do ch=getchar();
end
longint p[],vis[],ph[],pcnt=,T,n;
void init_p()
begin
ph[]=; ph[]=;
int64 temp;
for int i=;i<;i++ do
begin
if not vis[i] then
begin
p[pcnt]=i; ph[i]=i-; inc(pcnt);
end
for int j=;j<pcnt&&(temp=(int64)p[j]*i)<;j++ do
begin
vis[temp]=;
if i mod p[j]== then begin ph[temp]=ph[i]*p[j]; break; end
else ph[temp]=ph[i]*(p[j]-);
end
end
end
int64 solve(int n)
begin
int64 ans=0ll;
longint half=(int)(sqrt(n)+0.01);
if half*half==n then begin ans+=1ll*ph[half]*half/; dec(half); end
inc(ans); ans+=1ll*ph[n]*n/;
for int i=;i<=half;i++ do
if n mod i== then
begin
ans+=1ll*ph[i]*i/;
ans+=1ll*ph[n/i]*n/i/;
end
exit(ans*n);
}
int main()
begin
read(T); init_p();
for int i=;i<=T;i++ do
begin read(n); write("%lld",solve(n)); writeln; end
return ;
end
BZOJ2226:[SPOJ5971]LCMSum的更多相关文章
- [BZOJ2226][SPOJ5971]LCMSum(莫比乌斯反演)
2226: [Spoj 5971] LCMSum Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1949 Solved: 852[Submit][S ...
- [bzoj2226][Spoj5971]LCMSum_欧拉函数_线性筛
LCMSum bzoj-2226 Spoj-5971 题目大意:求$\sum\limits_{i=1}^nlcm(i,n)$ 注释:$1\le n\le 10^6$,$1\le cases \le 3 ...
- BZOJ2226 & SPOJ5971:LCMSum——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2226 题目大意:给定一个n,求lcm(1,n)+lcm(2,n)+……+lcm(n,n). ———— ...
- AHOI2018训练日程(3.10~4.12)
(总计:共90题) 3.10~3.16:17题 3.17~3.23:6题 3.24~3.30:17题 3.31~4.6:21题 4.7~4.12:29题 ZJOI&&FJOI(6题) ...
- 【BZOJ2226】[Spoj 5971] LCMSum 莫比乌斯反演(欧拉函数?)
[BZOJ2226][Spoj 5971] LCMSum Description Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n ...
- BZOJ2226: [Spoj 5971] LCMSum
题解: 考虑枚举gcd,然后问题转化为求<=n且与n互质的数的和. 这是有公式的f[i]=phi[i]*i/2 然后卡一卡时就可以过了. 代码: #include<cstdio> # ...
- BZOJ2226:LCMSum(欧拉函数)
Description Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n,n), where LCM(i,n) denotes t ...
- [BZOJ2226]LCMSum
转化一下,$\sum\limits_{i=1}^n[i,n]=n\sum\limits_{i=1}^n\dfrac i{(i,n)}$ 枚举$d=(i,n)$,上式变为$n\sum\limits_{d ...
- 【bzoj2226】[Spoj 5971] LCMSum 欧拉函数
题目描述 Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n,n), where LCM(i,n) denotes the Leas ...
随机推荐
- 面向XX程序设计到底是个啥
面向过程编程:面向(对着)-->过程(流程步骤)-->编程(码代码) IPO是啥 input(输入)-->process(过程处理)-->output(输出) 未来码代码的目的 ...
- Servlet共享数据
共享数据: 1.域对象:有一个作用范围的对象,可以在范围内共享数据 2.request域:代表一次请求范围,一般用于请求转发的多个资源中共享数据 方法: 1.存储数据:setAttrbute(Stri ...
- Linux服务器下对Oracle数据库expdp(导出)和impdp(导入)
紧接上篇文章,Oracle数据库架构已经创建完成,我的需求是:将老服务器上的数据库迁移到新的数据库上. 这就用到impdp(导入)操作. 要想实现对新数据库的impdp(导入)工作, 首先需要从老的数 ...
- Activiti学习笔记10 — 动态任务分配
动态任务分配使用的两种方式 一.通过特殊表达式,来获取任务信息 ,在流程 UserTask节点上设置 ${流程变量的Key} 1.流程定义 <?xml version="1.0&quo ...
- netty UnpooledHeapByteBuf 源码分析
UnpooledHeapByteBuf 是基于堆内存进行内存分配的字节缓冲区,没有基于对象池技术实现,这意味着每次I/O的读写都会创建一个新的UnpooledHeapByteBuf,频繁进行大块内存的 ...
- 01->OpenGL 实验环境配置(glut)及简单实例
-- 简介 -- OpenGL是通过数学等理论知识定义3D或2D模型,由计算机通过流水线渲染技术进行渲染,产生逼真的场景图像,电影和游戏中的特效都有用到.每每看到精美的画面,真想自己也能做出如此作 ...
- git提交流程简述
1.初始化:一个项目只执行一次 只要有.git隐藏文件夹就ok了 git init 或者 git clone url 2.为远程github仓库生成别名(remote-name就是远程仓库的别名)这一 ...
- JS函数 编程练习 使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数。
编程练习 使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数. 任务 第一步: 编写代码完成一个函数的定义吧. 第二步: 我们来补充函数体中的控制语句,完成函数功能吧. 提示: ...
- C# 创建DataTable并添加行和列
DataTable dt=new DataTable dt.Columns.Add("numview", typeof(Int32)); dt.Columns.Add(" ...
- python库之xgboost
一.安装 https://www.zhihu.com/question/46377605