[BZOJ2005]NOI2010能量采集|数学

数学题。。首先要知道点(x,y)与原点连线上整点的个数为gcd(x,y)(除原点)。我们可以找到最小的(x0,y0)在连线上,显然gcd(x0,y0)=1,那么所有(x0*k,y0*k)(x0*k<=n)都会在连线上,显然k最大为gcd(x,y),得证。其实还是很好想的,需要一点对函数的感觉。。根据这个可以枚举(x,y)算gcd,不过只能过8个点。。这样的话,可以考虑倒过来计算gcd为d的点数,直接不好算,我们先计算以d为公约数的点对数g[d],根据乘法原理显然g[d]=[n/d]*[m/d]。然后计算gcd为d的点对数f[d],只需要把公约数为d但还有大于d的公约数的点去掉就行了,所以可以得到f[d]=g[d]-∑f[k*d](k>=2&&k*d<=n),这个式子根据第一个结论的思路就可以想到。。

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
ll g[100005],f[100005],ans;
int i,j,n,m; 
int main()
{
	scanf("%d%d",&n,&m);
	if (m>n) swap(m,n);ans=0ll;
	for (i=m;i;i--)
	{
		f[i]=(ll)(m/i)*(ll)(n/i);
		for (j=2;j<=m/i;j++) f[i]-=f[j*i];
		ans+=f[i]*(ll)(2*i-1);
	}
	cout<<ans;
}


发布了164 篇原创文章 · 获赞 2 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览