• Gym 101350G


    题意

    有一个n*m的矩形,里面有k个炸弹,给出每个炸弹的坐标,计算在n*m的矩形中有多少子矩形内是不包含炸弹的。

    分析

    场上很是懵逼,赛后问学长说是容斥定理?一脸懵逼。。容斥不是初中奥数用在集合上的东西吗(雾

    先贴一下容斥的学习博客(貌似是我学长?):https://blog.csdn.net/usher_ou/article/details/68927439

    还有这个题的参考博客:https://blog.csdn.net/lyg_air/article/details/77606691

    侵删。

    首先我们来看一个预备知识:

    对于一个n*m的矩阵,它的子矩阵有多少个?我们可以看作一个组合的问题:在横着的n+1条边里选出两条来,从竖着的m+1条边里选出两条一共有多少选法?显然是C(2,n+1)*C(2,m+1)=n(n+1)/2*m(m+1)/2。

    容斥定理就是通过加加减减来求一个并集。对于这个题我们可以通过考虑它的逆问题来用容斥定理,它的逆问题显然是:有多少子矩阵包含至少一个炸弹。那么就是先把只含有一个炸弹的加起来,再减去含有两个炸弹的,再加上含有三个炸弹的····

    这是这个题的主要思路。那么还有两个小问题

    1 怎么枚举炸弹的数量?因为K最多只要20那么可以通过二进制进行枚举

    2 怎么计算包含某些数目炸弹的矩阵数?和上面计算n*m子矩阵的方法类似(一样),也是通过组合的方法。来看这张图

    比如要计算包含这三个点的举行数目,我们可以通过计算这三个点最大最小的横纵坐标确定一个范围,然后从这个范围外选边就可以了,写出来就是:minx*miny*(n-maxx+1)*(m-maxy+1);

    嗯,就是这样~A掉人生第一个容斥~

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 typedef long long LL;
     8 typedef unsigned long long ull;
     9 const int maxn=10000+10;
    10 const int INF=2147000000;
    11 struct Node{
    12     long long x,y;
    13 }node[maxn];
    14 long long T,n,m,k;
    15 
    16 int main(){
    17     scanf("%d",&T);
    18     for(int t=1;t<=T;t++){
    19         scanf("%lld%lld%lld",&n,&m,&k);
    20         for(int i=0;i<k;i++){
    21             scanf("%d%d",&node[i].x,&node[i].y);
    22         }
    23         LL ans=n*(n+1)/2*m*(m+1)/2;
    24         for(int i=1;i<(1<<k);i++){
    25             LL minx=INF,miny=INF,maxx=-INF,maxy=-INF;
    26             int cnt=0;
    27             for(int j=0;j<k;j++){
    28                 if(1<<j&i){
    29                     cnt++;
    30                     minx=min(minx,node[j].x);
    31                     miny=min(miny,node[j].y);
    32                     maxx=max(maxx,node[j].x);
    33                     maxy=max(maxy,node[j].y);
    34                 }
    35             }
    36             LL res=minx*miny*(n-maxx+1)*(m-maxy+1);
    37             //cout<<res<<endl;
    38             if(cnt%2)
    39                 ans-=res;
    40             else
    41                 ans+=res;
    42         }
    43         printf("%lld
    ",ans);
    44     }
    45 return 0;
    46 }
    View Code
  • 相关阅读:
    subtitleedit
    NHibernate.Mapping1.1.csgen 模板
    js jqueryhotkeys
    c#.net将对象序列化,反序列化json
    ruby document
    sqlserver2008新数据类型
    [转]杂记
    UVA 532 Dungeon Master
    UVA 10557 XYZZY
    UVA 10129 Play on Words
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/8868625.html
Copyright © 2020-2023  润新知