「CQOI2014」数三角形

本文详细解析了一种计数问题的算法实现,通过数学组合和最大公约数的概念,计算在给定网格中选取三个不共线点的方案数。算法首先计算所有可能的三元组,再扣除横竖共线和斜线共线的情况,最后给出参考C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

问题分析

可以先任意选\(3\)个数,然后减去三点共线的部分。

三点共线又分\(2\)种情况:

  • 横的或者竖的。这一部分方案数是\(n\times{m\choose 3}+m\times {n\choose3}\)
  • 斜的。不妨设线段一个端点在\((1,1)\),另一个端点在\((i,j)\)\(i,j>1\)。那么线段上的点总共有\(\gcd(i,j)+1\)个点。所以一条这样的线段的贡献是\(\gcd(i,j)-1\)。然后这样的线段共有\((n-i+1)\times(m-j+1)\)条,然后由于对称还要乘以二。

参考程序

#include <cstdio>
long long C3( long long n ) {
    return n * ( n - 1 ) * ( n - 2 ) / 6;
}
long long gcd( long long a, long long b ) {
    long long m = a % b;
    while( m ) {
        a = b; b = m; m = a % b;
    }
    return b;
}
int main() {
    long long n, m;
    scanf( "%lld%lld", &n, &m ); ++n, ++m;
    long long Ans = C3( n * m );
    Ans -= n * C3( m ) + m * C3( n );
    for( long long i = 2; i <= n; ++i )
        for( long long j = 2; j <= m; ++j ) {
            long long t = gcd( i - 1, j - 1 ) + 1;
            if( t >= 3 )  
                Ans -= ( n - i + 1 ) * ( m - j + 1 ) * ( t - 2 ) * 2;
        }
    printf( "%lld\n", Ans );
    return 0;
}

转载于:https://www.cnblogs.com/chy-2003/p/11457512.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值