您的位置:首页 > 其它

[NOI2010 能量采集]

2012-03-07 18:54 232 查看
[关键字]:数学 数论 公约数

[题目大意]:太麻烦自己看题吧……

//================================================================================================================

[分析]:先说我自己的80分解法,枚举每个(x,y)然后因为这个点所在的直线就是:y=kx,k=(y/gcd(x,y))/(x/gcd(x,y))因为k要约分所以就是同时除以gcd(x,y)又因为所有点必须是整数,所以在这条线上的点数就等于x/(x/gce(x,y))=gcd(x,y)(因为从(0,0)开始,自己算一下)。复杂度为O(nm)80分,大概20分钟32行,对于本菜性价比很高。然后再说一下100分的做法,既然枚举x、y超时,那么可以反向思维枚举d=gcd(x,y),所有以d为公约数的(x,y)个数为f[d]=(n/d)*(m/d),那么所有以d为最大公约数的(x,y)的个数为Σf[d]-f[i*d](就是减去所有以d的倍数为公约数的个数),ans+=f[d]*(2*d+1)。

[代码]:

100分

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

int N,M;
long long ans,f[100010];

int main()
{
scanf("%d%d",&N,&M);
for (int i=min(N,M);i>=1;--i)
{
f[i]=(long long)(N/i)*(long long)(M/i);
for (int j=2;(j<=N/i && j<=M/i);++j)
f[i]-=f[i*j];
ans+=f[i]*(i*2-1);
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: