3505: [Cqoi2014]数三角形

题目链接

题目大意:给一张m*n的网格,问这里面以网格为顶点的三角形有多少个

题解:坐标从0开始,所以有(n+1)*(m+1)个点,输入后n++,m++

不考虑共线的话是 C3nm ,然后需要减去横竖斜三种共线
横竖明显是 nC3m mC3n

下面考虑斜共线

结论: (0,0) (i,j) 连线上整点的个数为 gcd(i,j)+1 (包括 (0,0) (i,j) )

固定点 (0,0) ,枚举点 (i,j) ,这样就确定了斜率k,只需要统计k为正的即可(负的可以通过翻转,0和不存在已经计算过了),考虑所成线段,中间有 gcd(i,j)1 个点

乘上(n-i)*(m-j),即通过平移能找到多少条这样的线段

有两种情况:一种是枚举的(0,0)-(i,j),即从左下角->右上角,还有一种(i,0)->(0,j),即从右下角->左上角,这两种情况是相同的,最后要乘2

我的收获:思考方向

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

int n,m;
long long ans;  

long long C(int x){return (long long)x*(x-1)*(x-2)/6;}  

void work()
{
    ans=C(n*m)-C(n)*m-C(m)*n;
    for(int i=1;i<n;i++)  
        for(int j=1;j<m;j++)
            ans-=2ll*(__gcd(i,j)-1)*(n-i)*(m-j);
    printf("%lld\n",ans);  
}

void init(){
    cin>>n>>m;n++;m++;
} 

int main()  
{  
    init();
    work();
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值