• 数学(容斥计数):LNOI 2016 方


    Description

    上帝说,不要圆,要方,于是便有了这道题。由于我们应该方,而且最好能够尽量方,所以上帝派我们来找正方形
    上帝把我们派到了一个有N行M列的方格图上,图上一共有(N+1)×(M+1)个格点,我们需要做的就是找出这些格点形
    成了多少个正方形(换句话说,正方形的四个顶点都是格点)。但是这个问题对于我们来说太难了,因为点数太多
    了,所以上帝删掉了这(N+1)×(M+1)中的K个点。既然点变少了,问题也就变简单了,那么这个时候这些格点组成
    了多少个正方形呢?

    Input

    第一行三个整数 N, M, K, 代表棋盘的行数、 列数和不能选取的顶点个数。 保证 N, M >= 1, K <=(N + 1) ×
    (M + 1)。约定每行的格点从上到下依次用整数 0 到 N 编号,每列的格点依次用 0到 M 编号。接下来 K 行,每
    行两个整数 x,y 代表第 x 行第 y 列的格点被删掉了。保证 0 <=x <=N<=10^6, 0 <=y<=M<=10^6,K<=2*1000且不
    会出现重复的格点。

    Output

     仅一行一个正整数, 代表正方形个数对 100000007( 10^8 + 7) 取模之后的值

    Sample Input

    2 2 4
    1 0
    1 2
    0 1
    2 1

    Sample Output

    1
      这道题因为k很小可以用容斥, 所有正方形数-Σ每个点(在正方形上)的正方形数+Σ每个无序点对(在正方形上)的正方形数-Σ每个无序三个元组(在正方形上)的正方形数+Σ每个四元组(在正方形上)的正方形数
      然后我打的复杂化了,不过很好懂,几乎是望文生义……
      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 using namespace std;
      6 const int N=2010;
      7 const int Mod=100000007;
      8 typedef long long LL;
      9 LL Abs(LL x){return x<0?-x:x;}
     10 LL n,m,k,tot,x[N],y[N];
     11 LL Ask(LL a,LL b,LL c){
     12     LL ret,L;
     13     if(!a||!b||!c)return 0;
     14     if(a>c-1)a=c-1;
     15     if(b>c-1)b=c-1;
     16     ret=(2*c-a-1)*a/2;
     17     if(c-1>=b+1){
     18         L=min(a,c-b-1);
     19         ret+=b*L;
     20         ret-=(2*c-L-1)*L/2;
     21     }
     22     return (ret%Mod+Mod)%Mod;
     23 }
     24 LL Solve1(){
     25     LL ret=0,L,R,U,D;
     26     for(int i=1;i<=k;i++){
     27         L=min(x[i]-1,y[i]-1);ret+=L;
     28         L=min(n+1-x[i],y[i]-1);ret+=L;
     29         L=min(x[i]-1,m+1-y[i]);ret+=L;
     30         L=min(n+1-x[i],m+1-y[i]);ret+=L;
     31     }
     32     for(int i=1;i<=k;i++){
     33         U=x[i]-1;D=n+1-x[i];
     34         L=y[i]-1;R=m+1-y[i];
     35         ret+=Ask(L,R,U);
     36         ret+=Ask(L,R,D);
     37         ret+=Ask(U,D,L);
     38         ret+=Ask(U,D,R);
     39     }
     40     return ret%Mod;
     41 }
     42 
     43 
     44 LL Solve2(){
     45     LL ret=0,L;
     46     LL px,py,dx,dy;
     47     for(int i=1;i<=k;i++)
     48         for(int j=i+1;j<=k;j++){
     49             dx=x[j]-x[i];
     50             dy=y[j]-y[i];
     51             
     52             px=x[j]+dy;py=y[j]-dx;
     53             if(px>=1&&px<=n+1&&py>=1&&py<=m+1){
     54                 px=px-dx;py=py-dy;
     55                 if(px>=1&&px<=n+1&&py>=1&&py<=m+1)ret+=1;    
     56             }
     57             
     58             px=x[j]-dy;py=y[j]+dx;
     59             if(px>=1&&px<=n+1&&py>=1&&py<=m+1){
     60                 px=px-dx;py=py-dy;
     61                 if(px>=1&&px<=n+1&&py>=1&&py<=m+1)ret+=1;    
     62             }
     63             
     64             if((x[i]+x[j])%2==(y[i]+y[j])%2){
     65                 dx=2*x[i]-(x[i]+x[j]);
     66                 dy=2*y[i]-(y[i]+y[j]);
     67                 px=(x[i]+x[j]+dy)/2;
     68                 py=(y[i]+y[j]-dx)/2;
     69                 if(px>=1&&px<=n+1&&py>=1&&py<=m+1){
     70                     dx=-dx;dy=-dy;
     71                     px=(x[i]+x[j]+dy)/2;
     72                     py=(y[i]+y[j]-dx)/2;
     73                     if(px>=1&&px<=n+1&&py>=1&&py<=m+1)ret+=1;
     74                 }
     75             }
     76         }
     77     return ret%Mod;        
     78 }
     79 
     80 LL hshx[N],hshy[N];
     81 int cntx,cnty,vis[N][N];
     82 
     83 void Prepare(){
     84     for(int i=1;i<=k;i++){
     85         hshx[++cntx]=x[i];
     86         hshy[++cnty]=y[i];
     87     }
     88     sort(hshx+1,hshx+cntx+1);
     89     cntx=unique(hshx+1,hshx+cntx+1)-hshx-1;
     90     sort(hshy+1,hshy+cnty+1);
     91     cnty=unique(hshy+1,hshy+cnty+1)-hshy-1;
     92     for(int i=1;i<=k;i++){
     93         LL x_=lower_bound(hshx+1,hshx+cntx+1,x[i])-hshx;
     94         LL y_=lower_bound(hshy+1,hshy+cnty+1,y[i])-hshy;
     95         vis[x_][y_]=i;
     96     }
     97 }
     98 
     99 int Q(LL x,LL y){
    100     LL x_=lower_bound(hshx+1,hshx+cntx+1,x)-hshx;
    101     LL y_=lower_bound(hshy+1,hshy+cnty+1,y)-hshy;
    102     return (hshx[x_]==x&&hshy[y_]==y)*vis[x_][y_];
    103 }
    104 
    105 LL Solve3(){
    106     LL ret=0;
    107     LL px1,py1,px2,py2,dx,dy;
    108     for(int i=1;i<=k;i++)
    109         for(int j=i+1;j<=k;j++){
    110             dx=x[j]-x[i];
    111             dy=y[j]-y[i];
    112             
    113             px1=x[j]+dy;py1=y[j]-dx;
    114             if(px1>=1&&px1<=n+1&&py1>=1&&py1<=m+1){
    115                 px2=px1-dx;py2=py1-dy;
    116                 if(px2>=1&&px2<=n+1&&py2>=1&&py2<=m+1){
    117                     if(Q(px1,py1)>j)ret+=1;
    118                     if(Q(px2,py2)>j)ret+=1;
    119                 }
    120             }
    121             
    122             px1=x[j]-dy;py1=y[j]+dx;
    123             if(px1>=1&&px1<=n+1&&py1>=1&&py1<=m+1){
    124                 px2=px1-dx;py2=py1-dy;
    125                 if(px2>=1&&px2<=n+1&&py2>=1&&py2<=m+1){
    126                     if(Q(px1,py1)>j)ret+=1;
    127                     if(Q(px2,py2)>j)ret+=1;
    128                 }
    129             }
    130             
    131             if((x[i]+x[j])%2==(y[i]+y[j])%2){
    132                 dx=2*x[i]-(x[i]+x[j]);
    133                 dy=2*y[i]-(y[i]+y[j]);
    134                 px1=(x[i]+x[j]+dy)/2;
    135                 py1=(y[i]+y[j]-dx)/2;
    136                 if(px1>=1&&px1<=n+1&&py1>=1&&py1<=m+1){
    137                     dx=-dx;dy=-dy;
    138                     px2=(x[i]+x[j]+dy)/2;
    139                     py2=(y[i]+y[j]-dx)/2;
    140                     if(px2>=1&&px2<=n+1&&py2>=1&&py2<=m+1){
    141                         if(Q(px1,py1)>j)ret+=1;
    142                         if(Q(px2,py2)>j)ret+=1;
    143                     }
    144                 }
    145             }
    146         }
    147     return ret%Mod;
    148 }
    149 
    150 LL Solve4(){
    151     LL ret=0;
    152     LL px1,py1,px2,py2,dx,dy;
    153     for(int i=1;i<=k;i++)
    154         for(int j=i+1;j<=k;j++){
    155             dx=x[j]-x[i];
    156             dy=y[j]-y[i];
    157             
    158             px1=x[j]+dy;py1=y[j]-dx;
    159             if(px1>=1&&px1<=n+1&&py1>=1&&py1<=m+1){
    160                 px2=px1-dx;py2=py1-dy;
    161                 if(px2>=1&&px2<=n+1&&py2>=1&&py2<=m+1)
    162                     if(Q(px1,py1)>j&&Q(px2,py2)>j)ret+=1;
    163             }
    164             
    165             px1=x[j]-dy;py1=y[j]+dx;
    166             if(px1>=1&&px1<=n+1&&py1>=1&&py1<=m+1){
    167                 px2=px1-dx;py2=py1-dy;
    168                 if(px2>=1&&px2<=n+1&&py2>=1&&py2<=m+1)
    169                     if(Q(px1,py1)>j&&Q(px2,py2)>j)ret+=1;
    170             }
    171             
    172             if((x[i]+x[j])%2==(y[i]+y[j])%2){
    173                 dx=2*x[i]-(x[i]+x[j]);
    174                 dy=2*y[i]-(y[i]+y[j]);
    175                 px1=(x[i]+x[j]+dy)/2;
    176                 py1=(y[i]+y[j]-dx)/2;
    177                 if(px1>=1&&px1<=n+1&&py1>=1&&py1<=m+1){
    178                     dx=-dx;dy=-dy;
    179                     px2=(x[i]+x[j]+dy)/2;
    180                     py2=(y[i]+y[j]-dx)/2;
    181                     if(px2>=1&&px2<=n+1&&py2>=1&&py2<=m+1)
    182                         if(Q(px1,py1)>j&&Q(px2,py2)>j)ret+=1;
    183                 }
    184             }
    185         }
    186     return ret%Mod;
    187 }
    188 
    189 int main(){
    190     freopen("square.in","r",stdin);
    191     freopen("square.out","w",stdout);
    192     scanf("%lld%lld%lld",&n,&m,&k);
    193     for(LL L=min(m,n);L>=1;L--){
    194         tot+=(n-L+1)*(m-L+1)%Mod*L%Mod;
    195         if(tot>=Mod)tot-=Mod;
    196     }
    197     for(int i=1;i<=k;i++){
    198         scanf("%lld%lld",&x[i],&y[i]);
    199         x[i]+=1;y[i]+=1;
    200     }
    201     Prepare();
    202     tot-=Solve1();tot%=Mod;
    203     tot+=Solve2();tot%=Mod;
    204     tot-=Solve3();tot%=Mod;
    205     tot+=Solve4();tot%=Mod;    
    206     tot=(tot+Mod)%Mod;
    207     printf("%lld
    ",tot);
    208     return 0;
    209 }

      运算有些多,常数比较大,不开O2只有50分,优化的话,可以把LL改成int,Mod的时候有些地方可以改成减。

  • 相关阅读:
    MongoDB快速入门教程 (4.1)
    MongoDB快速入门教程 (3.3)
    MongoDB快速入门教程 (3.2)
    MongoDB快速入门教程(3.1)
    MongoDB快速入门教程 (2)
    MongoDB快速入门教程 (1)
    express高效入门教程(5)
    刷过的题 分类汇总
    Binary Tree & Divide Conquer 完整笔记------part 2
    binary search完整笔记
  • 原文地址:https://www.cnblogs.com/TenderRun/p/6001455.html
Copyright © 2020-2023  润新知