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很小可以用容斥, 所有正方形数-Σ每个点(在正方形上)的正方形数+Σ每个无序点对(在正方形上)的正方形数-Σ每个无序三个元组(在正方形上)的正方形数+Σ每个四元组(在正方形上)的正方形数
  然后我打的复杂化了,不过很好懂,几乎是望文生义……
 #include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=;
const int Mod=;
typedef long long LL;
LL Abs(LL x){return x<?-x:x;}
LL n,m,k,tot,x[N],y[N];
LL Ask(LL a,LL b,LL c){
LL ret,L;
if(!a||!b||!c)return ;
if(a>c-)a=c-;
if(b>c-)b=c-;
ret=(*c-a-)*a/;
if(c->=b+){
L=min(a,c-b-);
ret+=b*L;
ret-=(*c-L-)*L/;
}
return (ret%Mod+Mod)%Mod;
}
LL Solve1(){
LL ret=,L,R,U,D;
for(int i=;i<=k;i++){
L=min(x[i]-,y[i]-);ret+=L;
L=min(n+-x[i],y[i]-);ret+=L;
L=min(x[i]-,m+-y[i]);ret+=L;
L=min(n+-x[i],m+-y[i]);ret+=L;
}
for(int i=;i<=k;i++){
U=x[i]-;D=n+-x[i];
L=y[i]-;R=m+-y[i];
ret+=Ask(L,R,U);
ret+=Ask(L,R,D);
ret+=Ask(U,D,L);
ret+=Ask(U,D,R);
}
return ret%Mod;
} LL Solve2(){
LL ret=,L;
LL px,py,dx,dy;
for(int i=;i<=k;i++)
for(int j=i+;j<=k;j++){
dx=x[j]-x[i];
dy=y[j]-y[i]; px=x[j]+dy;py=y[j]-dx;
if(px>=&&px<=n+&&py>=&&py<=m+){
px=px-dx;py=py-dy;
if(px>=&&px<=n+&&py>=&&py<=m+)ret+=;
} px=x[j]-dy;py=y[j]+dx;
if(px>=&&px<=n+&&py>=&&py<=m+){
px=px-dx;py=py-dy;
if(px>=&&px<=n+&&py>=&&py<=m+)ret+=;
} if((x[i]+x[j])%==(y[i]+y[j])%){
dx=*x[i]-(x[i]+x[j]);
dy=*y[i]-(y[i]+y[j]);
px=(x[i]+x[j]+dy)/;
py=(y[i]+y[j]-dx)/;
if(px>=&&px<=n+&&py>=&&py<=m+){
dx=-dx;dy=-dy;
px=(x[i]+x[j]+dy)/;
py=(y[i]+y[j]-dx)/;
if(px>=&&px<=n+&&py>=&&py<=m+)ret+=;
}
}
}
return ret%Mod;
} LL hshx[N],hshy[N];
int cntx,cnty,vis[N][N]; void Prepare(){
for(int i=;i<=k;i++){
hshx[++cntx]=x[i];
hshy[++cnty]=y[i];
}
sort(hshx+,hshx+cntx+);
cntx=unique(hshx+,hshx+cntx+)-hshx-;
sort(hshy+,hshy+cnty+);
cnty=unique(hshy+,hshy+cnty+)-hshy-;
for(int i=;i<=k;i++){
LL x_=lower_bound(hshx+,hshx+cntx+,x[i])-hshx;
LL y_=lower_bound(hshy+,hshy+cnty+,y[i])-hshy;
vis[x_][y_]=i;
}
} int Q(LL x,LL y){
LL x_=lower_bound(hshx+,hshx+cntx+,x)-hshx;
LL y_=lower_bound(hshy+,hshy+cnty+,y)-hshy;
return (hshx[x_]==x&&hshy[y_]==y)*vis[x_][y_];
} LL Solve3(){
LL ret=;
LL px1,py1,px2,py2,dx,dy;
for(int i=;i<=k;i++)
for(int j=i+;j<=k;j++){
dx=x[j]-x[i];
dy=y[j]-y[i]; px1=x[j]+dy;py1=y[j]-dx;
if(px1>=&&px1<=n+&&py1>=&&py1<=m+){
px2=px1-dx;py2=py1-dy;
if(px2>=&&px2<=n+&&py2>=&&py2<=m+){
if(Q(px1,py1)>j)ret+=;
if(Q(px2,py2)>j)ret+=;
}
} px1=x[j]-dy;py1=y[j]+dx;
if(px1>=&&px1<=n+&&py1>=&&py1<=m+){
px2=px1-dx;py2=py1-dy;
if(px2>=&&px2<=n+&&py2>=&&py2<=m+){
if(Q(px1,py1)>j)ret+=;
if(Q(px2,py2)>j)ret+=;
}
} if((x[i]+x[j])%==(y[i]+y[j])%){
dx=*x[i]-(x[i]+x[j]);
dy=*y[i]-(y[i]+y[j]);
px1=(x[i]+x[j]+dy)/;
py1=(y[i]+y[j]-dx)/;
if(px1>=&&px1<=n+&&py1>=&&py1<=m+){
dx=-dx;dy=-dy;
px2=(x[i]+x[j]+dy)/;
py2=(y[i]+y[j]-dx)/;
if(px2>=&&px2<=n+&&py2>=&&py2<=m+){
if(Q(px1,py1)>j)ret+=;
if(Q(px2,py2)>j)ret+=;
}
}
}
}
return ret%Mod;
} LL Solve4(){
LL ret=;
LL px1,py1,px2,py2,dx,dy;
for(int i=;i<=k;i++)
for(int j=i+;j<=k;j++){
dx=x[j]-x[i];
dy=y[j]-y[i]; px1=x[j]+dy;py1=y[j]-dx;
if(px1>=&&px1<=n+&&py1>=&&py1<=m+){
px2=px1-dx;py2=py1-dy;
if(px2>=&&px2<=n+&&py2>=&&py2<=m+)
if(Q(px1,py1)>j&&Q(px2,py2)>j)ret+=;
} px1=x[j]-dy;py1=y[j]+dx;
if(px1>=&&px1<=n+&&py1>=&&py1<=m+){
px2=px1-dx;py2=py1-dy;
if(px2>=&&px2<=n+&&py2>=&&py2<=m+)
if(Q(px1,py1)>j&&Q(px2,py2)>j)ret+=;
} if((x[i]+x[j])%==(y[i]+y[j])%){
dx=*x[i]-(x[i]+x[j]);
dy=*y[i]-(y[i]+y[j]);
px1=(x[i]+x[j]+dy)/;
py1=(y[i]+y[j]-dx)/;
if(px1>=&&px1<=n+&&py1>=&&py1<=m+){
dx=-dx;dy=-dy;
px2=(x[i]+x[j]+dy)/;
py2=(y[i]+y[j]-dx)/;
if(px2>=&&px2<=n+&&py2>=&&py2<=m+)
if(Q(px1,py1)>j&&Q(px2,py2)>j)ret+=;
}
}
}
return ret%Mod;
} int main(){
freopen("square.in","r",stdin);
freopen("square.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&k);
for(LL L=min(m,n);L>=;L--){
tot+=(n-L+)*(m-L+)%Mod*L%Mod;
if(tot>=Mod)tot-=Mod;
}
for(int i=;i<=k;i++){
scanf("%lld%lld",&x[i],&y[i]);
x[i]+=;y[i]+=;
}
Prepare();
tot-=Solve1();tot%=Mod;
tot+=Solve2();tot%=Mod;
tot-=Solve3();tot%=Mod;
tot+=Solve4();tot%=Mod;
tot=(tot+Mod)%Mod;
printf("%lld\n",tot);
return ;
}

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

数学(容斥计数):LNOI 2016 方的更多相关文章

  1. 【BZOJ 4455】 [Zjoi2016]小星星 容斥计数

    dalao教导我们,看到计数想容斥……卡常策略:枚举顺序.除去无效状态.(树结构) #include <cstdio> #include <cstring> #include ...

  2. BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 4493  Solved: 2695[Submit][Statu ...

  3. Codeforces.997C.Sky Full of Stars(容斥 计数)

    题目链接 那场完整的Div2(Div1 ABC)在这儿.. \(Description\) 给定\(n(n\leq 10^6)\),用三种颜色染有\(n\times n\)个格子的矩形,求至少有一行或 ...

  4. 一本通 1783 矩阵填数 状压dp 容斥 计数

    LINK:矩阵填数 刚看到题目的时候感觉是无从下手的. 可以看到有n<=2的点 两个矩形. 如果只有一个矩形 矩形外的方案数容易计算考虑 矩形内的 必须要存在x这个最大值 且所有值<=x. ...

  5. CF1487G String Counting (容斥计数)

    传送门 考虑$c[i]>n/3$这个关键条件!最多有2个字母数量超过$n/3$! 没有奇数回文?长度大于3的回文串中间一定是长度为3的回文串,所以合法串一定没有长度=3的回文,也就是$a[i]\ ...

  6. ABC209F. Deforestation——DP(、数学容斥)

    题面 有 n n n 棵树排成一排,每棵树高度为 h i ( i ∈ [ 1 , n ] ) h_i~(i\in[1,n]) hi​ (i∈[1,n]) ,你现在要按照一个排列 P P P 的顺序去砍 ...

  7. 【BZOJ 4818】 4818: [Sdoi2017]序列计数 (矩阵乘法、容斥计数)

    4818: [Sdoi2017]序列计数 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 560  Solved: 359 Description Al ...

  8. Co-prime HDU - 4135_容斥计数

    Code: #include<cstdio> #include<cstring> #include<cmath> #include<iostream> ...

  9. How many integers can you find HDU - 1796_容斥计数

    Code: #include<cstdio> using namespace std; typedef long long ll; const int R=13; ll a[R]; ll ...

随机推荐

  1. Ext.Net学习笔记10:Ext.Net ComboBox用法

    ComboBox是最常用的控件之一,它与HTML中的Select控件很像,但可以进行多选.自定义显示格式.分页等. ComboBox用法 <ext:ComboBox runat="se ...

  2. 关于使用cocoaPods,import导入时第三方库头文件没有提示问题的解决办法

    估计有很多朋友在使用Xcode在项目中导入第三方库时,使用的是cocoaPods,但是在项目中使用此第三方库导入头文件时,输入#import后,并不会联想第三方库头文件(XXXX.h),需要我们手动输 ...

  3. Autolayout的在storyboard警告和错误

    警告 控件的frame不匹配所添加的约束, 比如比如约束控件的宽度为100, 而控件现在的宽度是110 错误 缺乏必要的约束, 比如只约束了宽度和高度, 没有约束具体的位置 两个约束冲突, 比如 1个 ...

  4. C语言——N个人围成一圈报数淘汰问题

    <一>问题描述: 有17个人围成一圈(编号为0-16),从第 0号的人开始从 1报数, 凡报到 3的倍数的人离开圈子,然后再数下去,直到最后只剩下一个人为止. 问此人原来的位置是多少号? ...

  5. void void*

    void类型及void指针 1.概述 许多初学者对C/C 语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并 详述void及void指 ...

  6. centos 交换分区

    内容来自:http://www.huzs.net/?p=1683 一般在桌面型的用不到,因为现在内存都比较大,服务器就不一样了,但是建议无论是在桌面还是服务器上,都设置 swap 以下操作都是在 ro ...

  7. C#基础(二)——C#中的构造函数

    构造函数主要是用来创建对象时为对象赋初值来初始化对象.总与new运算符一起使用在创建对象的语句中 .A a=new A(); 构造函数具有和类一样的名称:但它是一个函数具有函数的所有特性,同一个类里面 ...

  8. DIV+CSS 网页布局之:三列布局

    1.宽度自适应三列布局 三列布局的原理和两列布局的原理是一样的,只不过多了一列,只需给宽度自适应两列布局中间再加一列,然后重新计算三列的宽度,就实现了宽度自适应的三列布局. 同样的道理,更多列的布局, ...

  9. [转载] PowerMokito 使用

    一.为什么要使用Mock工具 在做单元测试的时候,我们会发现我们要测试的方法会引用很多外部依赖的对象,比如:(发送邮件,网络通讯,远程服务, 文件系统等等). 而我们没法控制这些外部依赖的对象,为了解 ...

  10. 安装 SQL Server 2012 的硬件和软件要求(官方全面)

    以下各节列出了安装和运行 SQL Server 2012 的最低硬件和软件要求. 有关 SharePoint 集成模式下 Analysis Services 的要求的详细信息,请参阅硬件和软件要求(S ...