【莫比乌斯】 BZOJ 2005 能量采集

通道

思路:

可以证明点(x,y)与(0,0)所连线段上不包含原点有的点为gcd(x,y)
于是问题就变成了求gcd(x,y)(1 <= x <= n,1 <= y <= m)的和;
可以设f[i]表示gcd为i的点对数有多少
首先公因数里面有i的点对数显然是(n / i) * ( m / i)
然后再减去f[i的倍数]就得到了f[i]

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define inf 0x7fffffff
#define ll long long
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll n,m;
ll ans,f[100005];
int main()
{
    n=read();m=read();
    if(n<m)swap(n,m);
    for(ll i=n;i;i--)
    {
        f[i]=(n/i)*(m/i);
        for(ll j=2*i;j<=n;j+=i)
            f[i]-=f[j];
        ans+=f[i]*(2*i-1);
    }
    printf("%lld",ans);
    return 0;
}
View Code

 

posted @ 2015-08-17 21:41  Rojo ゛  阅读(...)  评论(...编辑  收藏