您的位置:首页 > 其它

bzoj 2005 NOI 2010 能量采集

2013-12-23 16:44 363 查看
我们发现对于一个点(x,y),与(0,0)连线上的点数是gcd(x,y)-1

那么这个点的答案就是2*gcd(x,y)-1,那么最后的答案就是所有点

的gcd值*2-n*m,那么问题转化成了求每个点的gcd值的Σ

也即:Σi<=n Σj<=m gcd(i,j)

那么首先我们知道Σphi(d) d|n=n,所以我们可以将这个式子转化成

Σi<=n Σj<=m Σ d|gcd(i,j) phi(d)

那么对于矩阵n*m来说,我们将phi(d)累加了floor(n/d)*floor(m/d)次

所以对于所有的d,答案就是Σ d<=min(n,m) floor(n/d)*floor(m/d)*phi(d)

我们可以线性筛出欧拉函数表,然后线性的求解。

/**************************************************************
Problem: 2005
User: BLADEVIL
Language: Pascal
Result: Accepted
Time:36 ms
Memory:2568 kb
****************************************************************/

//By BLADEVIL
var
i, j                                :longint;
prime, mindiv, phi                  :array[0..100010] of int64;
ans                                 :int64;
n, m                                :int64;

procedure swap(var a,b:int64);
var
c                                   :int64;
begin
c:=a; a:=b; b:=c;
end;

begin
read(n,m);
if n>m then swap(n,m);
phi[1]:=1;
for i:=2 to n do
begin
if mindiv[i]=0 then
begin
inc(prime[0]);
prime[prime[0]]:=i;
mindiv[i]:=i;
phi[i]:=i-1;
end;
for j:=1 to prime[0] do
begin
if i*prime[j]>m then break;
mindiv[i*prime[j]]:=prime[j];
if i mod prime[j]=0 then
begin
phi[i*prime[j]]:=phi[i]*prime[j];
break;
end else
phi[i*prime[j]]:=phi[i]*(prime[j]-1);
end;
end;
for i:=1 to n do
ans:=ans+(n div i)*(m div i)*phi[i];
ans:=ans*2-n*m;
writeln(ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: