[hiho1476]-矩形计数-简单容斥

说在前面

本来是想做 计数类dp的(大概是…连通图计数之类的东西)
然后找到了这个题= =???
天天刷水题


题目

hiho1476传送门(需要登录才能看emmmm)

题目大意

给出一个 NM N ∗ M 的方格图,其中有 K K 个格子是黑色的
询问不包含黑色格子的子矩形有多少个
其中N,M1000 K10 K ≤ 10
图片名称
如图样例为24

输入输出格式

输入格式:
第一行三个整数 N,M,K N , M , K ,含义如题
接下来K行,每行两个数字 l,c l , c 表示所在行列

输出格式:
输出一个整数表示答案


解法

K K <script type="math/tex" id="MathJax-Element-221">K</script>这么小对不对!
直接容斥就好了=w=
(注意到不同情况可能有包含关系,但是这样容斥也是ok的)


下面是代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

int N , M , K , inf = 0x3f3f3f3f ;
struct Point{
    int x , y ;
} p[15] ;

void solve(){
    long long ans = 1LL * ( M * N ) * ( M * N ) ;//任意撒两个点
    ans += 1LL * N * M * M ;//同一行
    ans += 1LL * M * N * N ;//同一列
    ans += N * M ;//同一点
    ans >>= 2 ;//矩形总数

    int Fstate = ( 1 << K ) - 1 ;
    for( int i = 1 ; i <= Fstate ; i ++ ){
        long long fix = ( __builtin_popcount( i ) & 1 ? -1 : 1 ) ;
        int mnx = inf , mny = inf , mxx = 0 , mxy = 0 ;
        for( int j = 1 ; j <= K ; j ++ ) if( i & ( 1 << ( j - 1 ) ) ){
            mnx = min( mnx , p[j].x ) ;
            mny = min( mny , p[j].y ) ;
            mxx = max( mxx , p[j].x ) ;
            mxy = max( mxy , p[j].y ) ;
        }
        ans += fix * mnx * mny * ( N - mxx + 1 ) * ( N - mxy + 1 ) ;
    } printf( "%lld" , ans ) ;
}

int main(){
    scanf( "%d%d%d" , &N , &M , &K ) ;
    for( int i = 1 ; i <= K ; i ++ )
        scanf( "%d%d" , &p[i].x , &p[i].y ) ;
    solve() ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值