BZOJ3505 CQOI2014数三角形(组合数学)

  显然可以用总方案数减掉三点共线的情况。对于三点共线,一个暴力的做法是枚举起点终点,其间整点数量即为横纵坐标差的gcd-1。这样显然会T,注意到起点终点所形成的线段在哪个位置是没有区别的,于是枚举线段算出这样的线段条数就可以了。

  似乎可以莫比乌斯反演一波。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define ll long long
int n,m;
ll ans;
ll C(int x,int y){return 1ll*x*(x-1)*(x-2)/6;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj3505.in","r",stdin);
    freopen("bzoj3505.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),m=read();
    ans=C((n+1)*(m+1),3);
    for (int i=0;i<=n;i++)
        for (int j=0;j<=m;j++)
        if (i|j) ans-=1ll*(n+1-i)*(m+1-j)*(gcd(i,j)-1)<<(i&&j);
    cout<<ans;
    return 0;
}

 

posted @ 2018-08-26 11:43  Gloid  阅读(142)  评论(0编辑  收藏  举报