问题: 方

时间限制: 2 Sec  内存限制: 256 MB

题面


题目描述

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

输入格式

第一行三个整数 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且不 会出现重复的格点。

输出格式

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

样例输入

2 2 4

1 0

1 2

0 1

2 1

样例输出

1

题解


此题有毒!卡了我一整天。

从昨天下午一点多开始一直到今天的十一点,我才A掉了这到毒瘤题……

细节超多。

我们直接统计没有坏点的正方形个数显然不现实。暴力……没敢想。最起码$O(n^4)$的吧……

所以需要容斥原理。

我们处理出至少有零个坏点的正方形个数sum0,至少有一个坏点的正方形个数sum1,以此类推sum2、sum3和sum4的含义。

然后考虑怎么处理。

处理sum0:

我们通过观察得出这样的性质:

1.每一个斜正方形必定有唯一确定的包含它的最小的正正方形。

2.每一个边长为x的正正方形中包含着包括它自身共x个正方形。

于是我们推出式子:

$\sum\limits_{i=1}^{min(n,m)}{i*(n-i+1)*(m-i+1)}$

(i枚举边长,$(n-i+1)和(m-i+1)$的意义为平移后的个数。详情参见本人题解:数三角形)

然后就可以在O(n)时间内求出sum0。

处理sum1:

这道题最精髓(毒瘤)的部分。(查了若干份题解才搞明白还有一大堆结论没证……)

依然通过观察和理性思考,我们发现这样一个性质:

如果一个坏点在某一个正正方形的边上或者端点上,

那么它唯一对应这个正正方形中存在的某一个顶点均在正正方形边上的正方形(斜正方形或正正方形本身)

于是我们可以只去考虑该坏点位于正正方形的边上或者点上的情况。

问题转化为:过该坏点的正正方形有多少个。

枚举每一个坏点,我们考虑分情况讨论:该坏点在某个正方形的四个点上或四个边上。

四个顶点好求。由于保证是正正方形,我们只需要保证它不超过边界。

设该正方形距离左边界的距离为l,距右边界距离为r,距上边界距离为u,距下边界距离为d。

于是十分愉快一行取min走起:$sum1+=min(l,u),sum+=min(l,d),sum+=min(r,u),sum+=min(r,d)$;

接下来考虑坏点位于四个边上。

颓了一些性质(自己至今没有证上来……心里发虚)

我们只考虑左边界、右边界和上边界的关系来统计,其他直接旋转推广。

设该坏点距左边界的距离为x,距右边界的距离为y,距上边界的距离为h,

则有:

如果h<=min(x,y),对答案的贡献为h*(h+1)/2%mod;

如果min(x,y)<h<=max(x,y),对答案的贡献为min(x,y)*(min(x,y)+2)+min(x,y)*(h-min(x,y))

如果max(x,y)<h<=x+y,对答案的贡献为

min(x,y)*(min(x,y)+1)/2+min(x,y)*(max(x,y)-min(x,y))+(min(x,y)-1+min(x,y)-h+max(x,y))*(h-max(x,y))/2

如果h>x+y,对答案的贡献为x*y。

推广到四个方向,分别将左右上边界附成(l,r,u)(l,r,d)(u,d,l)(u,d,r)分别计算贡献即可。

处理sum2:

处理$sum2$的时候需要注意,我们处理出来的sum2是至少包含2个坏点的正方形总数。所以无需保证正方形的另外两个点不是坏点(我因为没想透卡了一小会儿)

所以我们只需要枚举两个坏点作为正方形的两个顶点,然后讨论这两个坏点作为正方形的边上的顶点和对角线上的顶点两种情况,讨论另外两个点是否在界内以及是否整点来统计答案。

作为边:1.另外两个点是$(A+D-B,B+A-C)(C+D-B,D+A-C)$

    2.另一方向的$(A+B-D,B+C-A)(C+B-D,D+C-A)$。

作为对角线,(利用全等三角形解方程可得):另外两个点是$((A-D+B+C)/2,B+C-(A-D+B+C)/2)((A-B+D+C)/2,A+D-(A-B+D+C)/2)$。

处理sum3、sum4:

这个显然和sum2放到一起就可以了。

网上的题解基本上一笔带过。然而细节还是需要处理一下的。

首先是判定问题。我最开始打了个暴搜判定,枚举每一个坏点坐标,匹配上了就返回1,否则一直搜到末尾返回0。

T到了2000ms。(真的飞起来了欸!)

然后学题解打hash链表,超快的说。783ms解决问题。

然而我sb的把模数设到了1e8+7,觉得可以借这个题给模数省一个define……

然后他就给了我一堆美妙的re。最开始re30,把数组压到1e7是re40,我意识到事情不太对,赶紧重开模数给它削了俩0,A了……

(好长啊 /仰望,给个推荐呗~)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#define mod 100000007
#define ll long long
#define int long long
#define K 1000007
using namespace std;
int n,m,k;
int sum0,sum1,sum2,sum3,sum4;
struct node{int x,y;}wor[300003];
struct hsss{int key,nxt;}data[300003];
int num,h[10000003];
//bool iswor[3003][3003];
inline int query(int x,int y)
{for(register int i=1;i<=k;++i)if(wor[i].x==x&&wor[i].y==y)return 1;return 0;
}
inline void ins(int key)
{int x=key%K;for(int i=h[x];i;i=data[i].nxt)if(data[i].key==key)return;data[++num].key=key;data[num].nxt=h[x];h[x]=num;
}
inline int cal(int x,int y,int h)
{ h-=1;if(x>y)swap(x,y); if(h<=x)return (ll)h*(h+1)/2%mod;if(h<=y)return ((ll)x*(x+1)/2+(ll)x*(h-x))%mod; if(h>=x+y)return (ll)x*y%mod; return ((ll)x*(x+1)/2+(ll)x*(y-x)+(ll)(x-1+x-h+y)*(h-y)/2)%mod;
}
/*inline bool query(int key)
{int x=key%K;for(int i=h[x];i;i=data[i].nxt)if(data[i].key==key) return 1;return 0;
}*/
inline void check(int x1,int y1,int x2,int y2)
{ if(x1<0||x1>n||x2<0||x2>n||y1<0||y1>m||y2<0||y2>m)return; int res=query(x1,y1)+query(x2,y2);sum2+=1;if(sum2>=mod)sum2-=mod;sum3+=res;if(sum3>=mod)sum3-=mod;sum4+=(res==2);if(sum4>=mod)sum4-=mod;
}
signed main()
{scanf("%lld %lld %lld",&n,&m,&k);for(register int i=1;i<=k;++i){scanf("%lld %lld",&wor[i].x,&wor[i].y);ins(wor[i].x*(m+1)+wor[i].y);}for(register int i=1;i<=min(n,m);++i){sum0+=i*(n-i+1)*(m-i+1)%mod;sum0%=mod;}for(register int i=1;i<=k;++i){int l=wor[i].x,r=n-wor[i].x,u=wor[i].y,d=m-wor[i].y;sum1+=min(l,u)+min(l,d)+min(r,u)+min(r,d);if(sum1>=mod)sum1-=mod;sum1+=cal(l,r,u);if(sum1>=mod)sum1-=mod;sum1+=cal(l,r,d);if(sum1>=mod)sum1-=mod;sum1+=cal(u,d,l);if(sum1>=mod)sum1-=mod;sum1+=cal(u,d,r);if(sum1>=mod)sum1-=mod;
/*        int l=wor[i].x,r=m-wor[i].x,u=wor[i].y,d=n-wor[i].y;int mn=min(l,r),mx=max(l,r);if(u<=mn)sum1+=(u+3)*u/2;else if(u>mn&&u<=mx)sum1+=(mn+3)*mn/2+(u-mn)*(mn+1);else if(u>=mx+mn+1)sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn+1)*mn/2;else sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn*2+1-u+mx)*(u-mx)/2;if(d<=mn)sum1+=(d+3)*d/2;else if(d>mn&&d<=mx)sum1+=(mn+3)*mn/2+(d-mn)*(mn+1);else if(d>=mx+mn+1)sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn+1)*mn/2;else sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn*2+1-d+mx)*(d-mx)/2;mn=min(u,d),mx=max(u,d);if(l<=mn)sum1+=(l+3)*l/2;else if(l>mn&&l<=mx)sum1+=(mn+3)*mn/2+(l-mn)*(mn+1);else if(l>=mx+mn+1)sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn+1)*mn/2;else sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn*2+1-l+mx)*(l-mx)/2;if(r<=mn)sum1+=(r+3)*r/2;else if(r>mn&&r<=mx)sum1+=(mn+3)*mn/2+(r-mn)*(mn+1);else if(r>=mx+mn+1)sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn+1)*mn/2;else sum1+=(mn+3)*mn/2+(mx-mn)*(mn+1)+(mn*2+1-r+mx)*(r-mx)/2;
*/}for(register int i=1;i<k;++i){for(register int j=i+1;j<=k;++j){int x1=wor[i].x,y1=wor[i].y,x2=wor[j].x,y2=wor[j].y;check(x1+y2-y1,y1+x1-x2,x2+y2-y1,y2+x1-x2);check(x1+y1-y2,y1+x2-x1,x2+y1-y2,y2+x2-x1);if((x1+x2+y1+y2)&1) continue;check(x1+x2+y2-y1>>1,y1+y2+x1-x2>>1,x1+x2+y1-y2>>1,y1+y2+x2-x1>>1);
/*if(A+D-B>0||B+A-C>0||A+D-B<m||B+A-C<n)if(C+D-B>0||C+D-B<m||D+A-C>0||D+A-C<n){sum2++;if(query(A+D-B,B+A-C)||query(C+D-B,D+A-C))sum3++;if(query(A+D-B,B+A-C)&&query(C+D-B,D+A-C))sum4++;}if((A-D+B+C)%2)continue;if((A-D+B+C)%2)continue;if((A-B+D+C)%2)continue;if((A-B+D+C)%2)continue;if((A-D+B+C)/2>0&&(A-D+B+C)/2<m&&B+C-(A-D+B+C)/2>0&&B+C-(A-D+B+C)/2<n)if((A-B+D+C)/2>0&&(A-B+D+C)/2<m&&A+D-(A-B+D+C)/2>0&&A+D-(A-B+D+C)/2<n){sum2++;if(query((A-D+B+C)/2,B+C-(A-D+B+C)/2)||query((A-B+D+C)/2,A+D-(A-B+D+C)/2))sum3++;if(query((A-D+B+C)/2,B+C-(A-D+B+C)/2)&&query((A-B+D+C)/2,A+D-(A-B+D+C)/2))sum4++;}
*/}}
//    cout<<sum0<<" "<<sum1<<" "<<sum2<<" "<<sum3<<" "<<sum4<<endl;cout<<((sum0-sum1+sum2-sum3/3+sum4/6)%mod+mod)%mod<<endl;return 0;
}

View Code

ps:注释掉的是我的调试和重构代码前的代码……写崩了……

转载于:https://www.cnblogs.com/xingmi-weiyouni/p/11237709.html

「题解」:[BZOJ4558]方相关推荐

  1. 「题解」蝙蝠侠的麻烦

    没 事 找 事 「我的做题历程」: step1:观察题面.   「蝙蝠侠需要找到一个最长的字符串,使得这个字符串作为一个子序列被包含在所有的三个字符串中」,可以得出这是一道最长公共子序列,而且有三个字 ...

  2. 「题解」:[组合数学]:Perm 排列计数

    题干: Description称一个1,2,-,N的排列P1,P2-,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,-N的排列中有多少是Magic的,答 ...

  3. 「题解」300iq Contest 2 B Bitwise Xor

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331B. 题意概述 给你一个长度为 nnn 的序列 aia_iai​,求一个最长的子序列满足所有子序列中的元 ...

  4. 「题解」:[线段树]:永无乡

    题面 题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 ...

  5. 「题解」USACO15FEB Fencing the Herd G

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书: 题目 题目链接:洛谷 P3122.USACO 官网. 题意概述 给你平面上的一些点和直线,有两种操作: 新加入一个点 (x,y)(x,y) ...

  6. 「题解」300iq Contest 2 H. Honorable Mention

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331H. 题意概述 给定一个长度为 n n n 的序列 a a a,有 q q q 次询问,每次询问给定三个 ...

  7. 「题解」LeetCode 顺时针打印矩阵

    题目页面_LeetCode_顺时针打印矩阵 分析 这道题目是按顺时针打印数组,其实就是读取的顺序与以前相比发生了变化. 那么就引出两个问题,边界问题和读取方向问题. 在边界问题上还是老样子,不要越界即 ...

  8. 「题解」老鼠与猫的交易

    题目描述 有一只老鼠很喜欢奶酪,但是奶酪被分别放在N个房间里,而且这些房间都有一只猫咪看守,现在它准和猫咪们 做个交易.它有M磅的猫食,想用这M磅猫食换取奶酪.在猫咪看守的每一个房间里有奶酪J[i]磅 ...

  9. 「题解」清华集训 2016 你的生命已如风中残烛

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书: 题目 题目链接:洛谷 P6672.UOJ 273. 题意简述 给你牌数为 m + 1 m+1 m+1 的牌堆,其中第 m + 1 m+1 ...

最新文章

  1. Atitit 桌面软件跨平台gui解决方案 javafx webview
  2. 【Foundation Frame】NSDictionary/NSMutableDictionary
  3. C语言实现字符串的加密和解密
  4. web.xml中的所有配置,Listener和Filter的加载顺序
  5. 返回后通知(After Return Advice)
  6. 2020牛客国庆集训派对day8G-Shuffle Cards【Splay】
  7. html中常见的小问题(1)
  8. FFMpeg在Windows环境下的编译
  9. leetcode —— 面试题61. 扑克牌中的顺子
  10. 机器学习实战10-Artificial Neural Networks人工神经网络简介(mnist数据集)
  11. SAP License:SAP常用基本小技巧
  12. 电商是真的难做了吗?
  13. SQL Server审核功能–发现和体系结构
  14. WindowsServers2019上手体验
  15. python实现不同图像数据的叠加处理、实现多张图像数据以子图形式组合为新的图像数据【图像叠加、图像组合】
  16. WebServer服务器开发的基本逻辑
  17. BubbleSort C#
  18. matlab 陈学松,基于强化学习的空调系统运行优化OPTIMIZATIONOF-同济大学.PDF
  19. 线性代数————思维导图(上岸必备)(矩阵部分)
  20. 2018 年寒假/春节,来蓝鲸玩吧!

热门文章

  1. Vue 3 首个 RC 版本发布
  2. Bare HTTP不完全是RESTful
  3. 使用ANNdotNET GUI工具创建CIFAR-10深度学习模型
  4. IIS日志-网站运维的好帮手
  5. 位置路径 usb 获取_USB4规范解读(二):详解USB4的传输路径
  6. Java中重定向,转发深入理解 2021-04-26
  7. java poi教程_Java完成POI的功能
  8. 2020年最好用的手机是哪一款_2020年入手5G手机最佳时期到了:5款最佳手机,您认可哪款...
  9. 密码可见_无密码身份认证即将来临
  10. eclipse 2019-12版本安装svn