未经博主同意不能转载

4558: [JLoi2016]方

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 362  Solved: 162

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

HINT

Source

【分析】

  终于A了,昨晚做了一晚上了。

  容斥真的很容易搞错。

  注意这题的正方形可以是【斜着的】

  于是怎么算呢?首先假设没有删除点,答案=总方案-至少有一个删除点的方案数

  1、总方案怎么算?

  你会觉得斜着的正方形很难算,但是每个正方形都有外接正方形,对于边长为a的正的正方形来说,他是a个正方形的外接正方形,于是枚举外接正方形边长即可。

  2、至少有一个删除点的方案数?

  这个的答案=SIGEMA(枚举每一个删除点然后算以他为顶点的正方形的方案数)-至少两个删除点的方案数+至少三个删除点的方案数-4个删除点的方案数

  3、枚举每一个删除点然后算以他为顶点的正方形的方案数?

  【这里的正方形还是有斜的】,但是!这个删除点一定在这个以它的顶点的正方形的外接正方形的某条边长上(或角上),所以只需计算正的正方形且某条边长覆盖这个点的方案数。

  【这个貌似是最难算的,因为看不懂题解于是我自己Y了一个计算方法】:

  

  分成四部分来做(还有一部分是删除点是顶点,这个比较容易就不说了,所以现在计算的答案是不包含删除点是顶点的,只包含删除点在四边上)

  四部分是左半、右半、上半、下半,图示蓝框是左半。

  左半部分就是说删除点在正方形右边长上。

  【还是把正方形画一画吧】

  

   根据蓝框的横宽可以知道正方形边长的一个极限,于是可以把图形降维,变成一维上的问题。

  

  问题变成:0~n数轴上有一点x,问你长度为[1,r]且为整数的,并覆盖了x点的区间有多少个(端点覆盖不算覆盖)。

  之前做的一道概率题已让我对此问题有所体会,这里再用一个小容斥最好算了:总区间-不覆盖x的区间。

  即(0~n)中长度[1,r]的整区间-(0~x)中长度[1,r]的整区间-(x~n)中长度[1,r]的整区间。

  这样就求出来了这个答案,记为a1。【记得要把删除点为正方形角的加上

  4、问题还没有结束,对于2个、3个、4个删除点,我们枚举两个删除点可以确定这个正方形(有三种形态)

  然后这三个答案一起算。记为a2,a3,a4

  最后答案=总-a1+a2-a3/3+a4/6【因为你枚举两个点,所以同一个正方形有可能算多遍,于是需要除,a3加的时候是加TMP,具体看代码】

  【说一下这个为什么?我其实我己都没想清楚这个,也是看别人这样写的】

  首先a2计算是正确的,你假设两个未删除点,枚举的也是两个未删除点。

  a3的话,你应该枚举三个未删除的点,但是你只枚举两个,第三个是计算出来的。

  假设真的只有三个点,对于同一个正方形,你枚举了$C_{3}^{2}$次,实际上应该枚举$C_{3}^{3}$次,是3倍,所以要除以3。

  不过至少是3的话还有可能是4,你枚举了$C_{4}^{2}$次,实际上应该枚举$C_{4}^{3}$次,所以要*2/3

  a4的话,你枚举了$C_{4}^{2}$次,实际是$C_{4}^{4}$次,所以要除以6。

  确定正方形的三种形态的话,我也是自己Y了一下,经验就是用向量!,向量是解决几何问题的最好工具!【不懂可以看看代码怎么打

  

  【这篇写得够认真了吧??】

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 2010
#define Maxm 1000010
#define Mod 100000007
#define LL long long int mymin(int x,int y) {return x<y?x:y;} int nx[Maxn],ny[Maxn],rx[Maxm],ry[Maxm];
bool vis[Maxn][Maxn]; struct node
{
int x,id;
}t[Maxn];
bool cmp(node x,node y) {return x.x<y.x;} int check(int x,int y)
{
int ret=;
if(vis[nx[x]][ny[x]]) ret++;
if(vis[nx[y]][ny[y]]) ret++;
if(vis[nx[x]][ny[y]]) ret++;
if(vis[nx[y]][ny[x]]) ret++;
return ret;
} int n,m,k;
void init()
{
for(int i=;i<=k;i++) t[i].x=nx[i],t[i].id=i;sort(t+,t++k,cmp);
int p=;rx[t[].x]=p;
for(int i=;i<=k;i++)
{
if(t[i].x!=t[i-].x) p++,rx[t[i].x]=p;
// nx[t[i].id]=p;
}
for(int i=;i<=k;i++) t[i].x=ny[i],t[i].id=i;sort(t+,t++k,cmp);
p=;ry[t[].x]=p;
for(int i=;i<=k;i++)
{
if(t[i].x!=t[i-].x) p++,ry[t[i].x]=p;
// ny[t[i].id]=p;
}
memset(vis,,sizeof(vis));
for(int i=;i<=k;i++) vis[rx[nx[i]]][ry[ny[i]]]=;
} int cal(int x,int y)
{
if(!x) return ;
y=min(y,x);
int l=x-y+,r=x;
return (1LL*(l+r)*(r-l+)/)%Mod;
} int a1,a2,a3,a4;
void get_ans(int x1,int y1,int x2,int y2)
{
if(x1<||x1>n||y1<||y1>m||x2<||x2>n||y2<||y2>m) return;
int tmp=;
if(rx[x1]&&ry[y1]&&vis[rx[x1]][ry[y1]]) tmp++;
if(rx[x2]&&ry[y2]&&vis[rx[x2]][ry[y2]]) tmp++;
a2++;if(tmp) a3+=tmp;if(tmp>) a4++;
} void solve(int x1,int y1,int x2,int y2)
{
int dx=x1-x2,dy=y1-y2;
get_ans(x1+dy,y1-dx,x2+dy,y2-dx);
get_ans(x1-dy,y1+dx,x2-dy,y2+dx);
if(abs(dx+dy)&) return;
get_ans((x1+x2+dy)/,(y1+y2-dx)/,(x1+x2-dy)/,(y1+y2+dx)/);
} int main()
{
scanf("%d%d%d",&n,&m,&k);
int ans=;
for(int i=;i<=n&&i<=m;i++) ans=(ans+1LL*(n+-i)*(m+-i)%Mod*i%Mod)%Mod;
for(int i=;i<=k;i++)
{
scanf("%d%d",&nx[i],&ny[i]);
}
for(int i=;i<=k;i++)
{
a1+=cal(n,ny[i])-cal(nx[i],ny[i])-cal(n-nx[i],ny[i]);a1%=Mod;
a1+=cal(n,m-ny[i])-cal(nx[i],m-ny[i])-cal(n-nx[i],m-ny[i]);a1%=Mod;
a1+=cal(m,nx[i])-cal(ny[i],nx[i])-cal(m-ny[i],nx[i]);a1%=Mod;
a1+=cal(m,n-nx[i])-cal(ny[i],n-nx[i])-cal(m-ny[i],n-nx[i]);a1%=Mod;
a1+=min(nx[i],ny[i])+min(n-nx[i],m-ny[i])+min(n-nx[i],ny[i])+min(nx[i],m-ny[i]);a1%=Mod;
}
init();
for(int i=;i<=k;i++)
for(int j=i+;j<=k;j++)
{
solve(nx[i],ny[i],nx[j],ny[j]);
}
// printf("%d\n",a3);
printf("%d\n",((ans-a1+a2-a3/+a4/)%Mod+Mod)%Mod);
return ;
}

2017-04-21 09:25:43

【BZOJ 4558】 4558: [JLoi2016]方 (计数、容斥原理)的更多相关文章

  1. BZOJ.4558.[JLOI2016]方(计数 容斥)

    BZOJ 洛谷 图基本来自这儿. 看到这种计数问题考虑容斥.\(Ans=\) 没有限制的正方形个数 - 以\(i\)为顶点的正方形个数 + 以\(i,j\)为顶点的正方形个数 - 以\(i,j,k\) ...

  2. 4558: [JLoi2016]方

    4558: [JLoi2016]方 https://lydsy.com/JudgeOnline/problem.php?id=4558 分析: 容斥原理+各种神奇的计数. 如果没有被删除了的点的话,直 ...

  3. bzoj4558[JLoi2016]方 容斥+count

    4558: [JLoi2016]方 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 452  Solved: 205[Submit][Status][D ...

  4. BZOJ 3235: [Ahoi2013]好方的蛇

    BZOJ 3235: [Ahoi2013]好方的蛇 标签(空格分隔): OI-BZOJ OI-DP OI-容斥原理 Time Limit: 10 Sec Memory Limit: 64 MB Des ...

  5. bzoj 2111: [ZJOI2010]Perm 排列计数 (dp+卢卡斯定理)

    bzoj 2111: [ZJOI2010]Perm 排列计数 1 ≤ N ≤ 10^6, P≤ 10^9 题意:求1~N的排列有多少种小根堆 1: #include<cstdio> 2: ...

  6. 集训队8月9日(组合计数+容斥原理+Mobius函数)

    刷题数:4 今天看了组合计数+容斥原理+Mobius函数,算法竞赛进阶指南169~179页 组合计数 https://www.cnblogs.com/2462478392Lee/p/11328938. ...

  7. 【BZOJ】4558: [JLoi2016]方

    [题意]给定有(n+1)*(m+1)个点的网格图,其中指定k个点不合法,求合法的正方形个数(四顶点合法). [算法]计数 [题解]斜着的正方形很麻烦,所以考虑每个斜正方形其外一定有正的外接正方形. 也 ...

  8. bzoj千题计划281:bzoj4558: [JLoi2016]方

    http://www.lydsy.com/JudgeOnline/problem.php?id=4558 容斥原理 全部的正方形-至少有一个点被删掉的+至少有两个点被删掉的-至少有3个点被删掉的+至少 ...

  9. BZOJ 4517: [Sdoi2016]排列计数 [容斥原理]

    4517: [Sdoi2016]排列计数 题意:多组询问,n的全排列中恰好m个不是错排的有多少个 容斥原理强行推♂倒她 $恰好m个不是错排 $ \[ =\ \ge m个不是错排 - \ge m+1个不 ...

随机推荐

  1. Python练习-Property的用法

    # 编辑者:闫龙 #要求一:自定义用户信息数据结构,写入文件,然后读出内容,利用eval重新获取数据结构 with open('user.db','w') as write_file:#创建并以写入的 ...

  2. 使用mysql的SUBSTRING_INDEX函数解决项目中编码非重复问题的实现方案!

    一 SUBSTRING_INDEX函数介绍 作用:按关键字截取字符串 substring_index(str,delim,count) 说明:substring_index(被截取字段,关键字,关键字 ...

  3. 一个脚本和一个容易疏忽的问题strcmp、strncmp、memcmp的用法【原创】

    一个容易疏忽的问题: strcmp.strncmp.memcmp, 对于memcmp进行字符串比较时可能会出现内存重叠的情况 status = strncmp(xdev->product, &q ...

  4. Python爬虫---requests库快速上手

    一.requests库简介 requests是Python的一个HTTP相关的库 requests安装: pip install requests 二.GET请求 import requests # ...

  5. 使用脚本实现killproc的功能

    在shell提示符号下输入type killproc,会发现killproc实在 /sbin/目录下,通过man killproc可以查看这个脚本(姑且这么称为脚本)的用法,现在,把这个脚本的实现过程 ...

  6. SSD的SLC MLC 和TLC哪个好?

    <1>SLC = Single-Level Cell ,即1bit/cell,速度快寿命长,价格超贵(约MLC 3倍以上的价格),约10万次擦写寿命MLC = Multi-Level Ce ...

  7. Python 模块进阶

    import导入模块 1. import 搜索路径 import sys sys.path 例子: In [1]: import sys In [2]: sys.path Out[2]: ['', ' ...

  8. 如何用纯CSS布局两列,一列固定宽度,另一列自适应?

    大家都知道好多网站都是左右布局的,很多公司在笔试和面试环节也常常问这个问题.一个去网易的师兄说14年腾讯面试的时候问过这个问题,网易在笔试和面试时候也问过这个问题,还有很多互联网公司也都涉及到这个问题 ...

  9. JAVA复习笔记分布式篇:kafka

    前言:第一次使用消息队列是在实在前年的时候,那时候还不了解kafka,用的是阿里的rocket_mq,当时觉得挺好用的,后来听原阿里的同事说rocket_mq是他们看来kafka的源码后自己开发了一套 ...

  10. nginx重写链接

    location ~ /send.redir {             if ( $query_string ~ “url=(?<path>.+)” ) {rewrite ^.* htt ...