没想到NOI竟然还有这种数学题,看来要好好学数论了……

网上的题解:

完整的结题报告:

首先我们需要知道一个知识,对于坐标系第一象限任意的整点(即横纵坐标均为整数的点)p(n,m),其与原点o(0,0)的连线上除过原点整点的个数为gcd(n,m)。其他象限上个数则为gcd(abs(n),abs(m)),这里的gcd(a,b)是指a与b的最大公约数(Greastest Common Divisor),abs(a)是指数a的绝对值。
证明:
考虑在op上最小的一个整点(x,y),这里的最小是指横纵坐标绝对值最小,x与y必然满足gcd(x,y)=1,即x与y互质。因为若不互质的话,将x与y均除去他们的公约数后可以产生一个更小的整点。则显然有(kx,ky){x<=kx<=n,k属于正整数}也在线段op上,而且这些点也是op上全部的整点,显然这些点的个数等于最大的那个k。为方便叙述我们直接将其称为k,其满足kx=n,ky=m。则显然k=gcd(n,m),证明完毕。
则现在我们只需要求出每一个gcd(n,m)即可,这里我们可以使用经典的欧几里德算法,其的复杂度为O(lgb),b为两个数中较小的那个。总的复杂度将为O(n^2lgn)但是考虑到此题的规模极大,此方法必然超时。
进一步考虑,我们不难发现要求的最大公约数的规模相对于所有数对的规模要小的多。所以我们可以转而求对于一个数p(p<min(n,m)),满足gcd(a,b)=p的数对(a,b)的个数。
令num[i]表示最大公约数为i的数对的个数,bound为min(n,m)。首先可以知道公约数有i的数对的个数应为(n div i)*(m div i),这个是比较好想的,然而并没有满足要求,因为i并不为最大公约数。不过处理方法很简单,考虑到这些当前的数对可能存在比i更大的公约数为2i,3i,4i...ki(ki<=bound),只需将这些数对删去即可。
这样我们就有了整体框架,首先可以直接求出num[bound] = (n div bound)*(m div bound),按照从大到小的顺序求num[i]即可,num[i] = (n div i)*(m div i)-Sigma(num[ki]) , 1<=ki<=bound) (那个求和的符号我打不出来...)
则代价的总和为2*Sigma(num[i]*i)-nm(因为题目中要求的线段上的整点不包括端点,而我们算的gcd(a,b),其中包括了点(a,b))。

我的代码:

 var n,m,ans,d:int64;
g:longint;
f:array[..] of int64;
function min(x,y:int64):int64;
begin
if x<y then min:=x else min:=y;
end;
begin
ans:=;
readln(n,m);
for g:=min(n,m) downto do
begin
f[g]:=(n div g)*(m div g);
d:=g+g;
while d<=min(n,m) do
begin
dec(f[g],f[d]);
inc(d,g);
end;
end;
for g:=min(n,m) downto do
inc(ans,f[g]*(*g-));
writeln(ans);
end.

ps:f[i]:=(n div i )* (m div i)

在这个式子中,即使 f 数组为 int64 数组,但n,m为 longint ,当n=m=100000时还是会发生溢出,所以n,m也必为 inf64

这种容易忽视的错误需要注意,即参与四则运算的变量必须能承载运算结果!

UPD:更简单的莫比乌斯反演

sigma(gcd(x,y))1<=x<=n,1<=y<=m=sigma(fai[k]*(n/k)*(m/k)) 1<=k<=min(n,m)

线性筛就行了。

代码:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 100000+5
#define maxm 100000+5
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
ll n,m,p[maxn],tot,fai[maxn];
ll ans;
bool v[maxn];
inline void get()
{
fai[]=;
for2(i,,m)
{
if(!v[i])p[++tot]=i,fai[i]=i-;
for1(j,tot)
{
int k=p[j]*i;
if(k>m)break;
v[k]=;
if(i%p[j])fai[k]=fai[i]*(p[j]-);
else {fai[k]=fai[i]*p[j];break;}
}
}
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();m=read();
if(n<m)swap(n,m);
get();
for1(i,m)ans+=fai[i]*(n/i)*(m/i);
cout<<n*m+*(ans-n*m)<<endl;
return ;
}

NOI2010能量采集(数论)的更多相关文章

  1. BZOJ 2005: [Noi2010]能量采集( 数论 + 容斥原理 )

    一个点(x, y)的能量损失为 (gcd(x, y) - 1) * 2 + 1 = gcd(x, y) *  2 - 1. 设g(i)为 gcd(x, y) = i ( 1 <= x <= ...

  2. Luogu P1447 [NOI2010]能量采集 数论??欧拉

    刚学的欧拉反演(在最后)就用上了,挺好$qwq$ 题意:求$\sum_{i=1}^{N}\sum_{j=1}^{M}(2*gcd(i,j)-1)$ 原式 $=2*\sum_{i=1}^{N}\sum_ ...

  3. [BZOJ2005][Noi2010]能量采集 容斥+数论

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 4394  Solved: 2624[Submit][Statu ...

  4. BZOJ 2015:[Noi2010]能量采集(数论+容斥原理)

    2005: [Noi2010]能量采集 Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物 ...

  5. BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 4493  Solved: 2695[Submit][Statu ...

  6. luogu1447 [NOI2010]能量采集 莫比乌斯反演

    link 冬令营考炸了,我这个菜鸡只好颓废数学题了 NOI2010能量采集 由题意可以写出式子: \(\sum_{i=1}^n\sum_{j=1}^m(2\gcd(i,j)-1)\) \(=2\sum ...

  7. BZOJ 2005: [Noi2010]能量采集

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 3312  Solved: 1971[Submit][Statu ...

  8. noi2010 能量采集

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MB Submit: 3068  Solved: 1820 [Submit][Sta ...

  9. bzoj2005: [Noi2010]能量采集

    lsj师兄的题解 一个点(x, y)的能量损失为 (gcd(x, y) - 1) * 2 + 1 = gcd(x, y) *  2 - 1. 设g(i)为 gcd(x, y) = i ( 1 < ...

  10. 2005: [Noi2010]能量采集

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 1831  Solved: 1086[Submit][Statu ...

随机推荐

  1. discuz x3插件开发傻瓜图文教程,用demo说话

    此demo功能是在模板footer部位插入一段javascript代码,这段代码可以是alert提示,也可以是加载广告等等. 第一步: 在config\config_global.php 文件里设置$ ...

  2. 源码编译安装LNMP环境及配置基于域名访问的多虚拟主机

    实验环境及软件版本: CentOS版本: 6.6(2.6.32.-504.el6.x86_64) nginx版本: nginx-1.6.2 mysql版本:  Mysql-5.6.23 php版本: ...

  3. 以a为变量名,给出下列描述的定义

    a)一个整型数(An integer) b) 一个指向整型数的指针(A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to ...

  4. 1061. Dating (20)

    #include <stdio.h> #include <map> #include <string.h> #include <ctype.h> usi ...

  5. CodeBlocks去掉拼写检查

    打开: 选择Compiler... 将红框里面的勾都点掉即可!

  6. PHP内置函数

    1 变量函数 a.is_xxx函数用来判断变量类型       is_int.is_integer.is_long,判断变量是否是整型       is_float.is_double.is_real ...

  7. 2016 系统设计第一期 (档案一)MVC 和 Bootstrap 表单转换

    bootstrap <form role="form"> <div class="form-group"> <label for= ...

  8. (转载)Cocos2dx-OpenGL ES 2.0教程:你的第一个三角形(1)

    前言 在本系列教程中,我会以当下最流行的2D引擎Cocos2D-X为基础,介绍OpenGL ES 2.0的一些基本用法.本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2D-X过程中,知其然 ...

  9. jsf2.0视频

    jsf2.0 入门视频 教程   需要的看下.初次录视频.还有很多需要完善. JSF交流QQ群84376982 JSF入门视频下载地址  http://pan.baidu.com/s/1jG3y4T4 ...

  10. sql之透视

    1.透视原理:就是将查询结果进行转置 下面就举例来说明: 执行下面语句:检查是否含有表 dbo.Orders,如果有就将表删除: if OBJECT_ID('dbo.Orders','U') is n ...