未经博主同意不能转载

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. 天梯赛 L2-023. (模拟) 图着色问题

    题目链接 题目描述 图着色问题是一个著名的NP完全问题.给定无向图 G = (V, E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色? 但本题并不是要你解决这 ...

  2. llg的农场(farm)

    评测传送门 [题目描述] llg 是一名快乐的农民,他拥有一个很大的农场,并且种了各种各样的瓜果蔬菜,到了每年秋天,他就可以把所有蔬菜水果卖到市场上,这样他就可以获利.但今年他遇到了一个难题——有许多 ...

  3. ubuntu的PPA

    PPA,表示Personal Package Archives,也就是个人软件包集很多软件包由于各种原因吧,不能进入官方的Ubuntu软件仓库.为了方便Ubuntu用户使用,launchpad.net ...

  4. ASP.NET 实现Base64文件流下载PDF

    因为业务需要调用接口获取的是 Base64文件流 需要提供给客户下载PDF文档 源码部分借鉴网上,具体地址忘记了. //Base64文件流 byte[] buffer = Convert.FromBa ...

  5. kettle简单插入与更新

    Kettle简介:Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.Kettle 中文名称叫水壶,该项目的主程序员MATT 希望 ...

  6. [shell]shell中if语句的使用

    转自:http://lovelace.blog.51cto.com/1028430/1211353 bash中如何实现条件判断?条件测试类型:    整数测试    字符测试    文件测试 一.条件 ...

  7. HTML 多张图片无缝连接

    <table border="0" cellspacing="0" cellpadding="0" style="heigh ...

  8. 32 Profiling Go Programs 分析go语言项目

    Profiling Go Programs  分析go语言项目 24 June 2011 At Scala Days 2011, Robert Hundt presented a paper titl ...

  9. Python匿名函数详解

    python 使用 lambda 来创建匿名函数. lambda这个名称来自于LISP,而LISP则是从lambda calculus(一种符号逻辑形式)取这个名称的. 在Python中,lambda ...

  10. python随笔(三)

    在对字符串的操作中,s[::-1]表示将字符串逆序输出. 字符串本身不能改变(管理者而非所有者) 列表的内容是可以改变的,且列表的内容可以不仅仅是字符串.对于一个列表,注意b=a和b=a[:]的区别. ...