bzoj4558[JLoi2016]方 容斥+count
2017-12-13 22:12
316 查看
4558: [JLoi2016]方
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 452 Solved: 205
[Submit][Status][Discuss]
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 41 0
1 2
0 1
2 1
Sample Output
1 并没有调出来,调出来也是TLE容斥,ans=所有格点正方形-至少含一个非法点正方形+至少含2个-至少含3个+至少含4个
容斥很简单,主要就是统计方案难啊
由于正方形有斜放的,我们规定一个n*n的框架
顶点在框架边上的正方形有i个
考虑对于每一个非法点,除去以它为顶点的正方形(正方/斜放都要考虑)
枚举两个非法点,计算以它们为顶点的正方形另外两个点,对于含2,3,4的贡献答案。
判断正方形的顶点是否存在,应该用hash表,由于懒,我用了stl,估计要挂。。
推荐blog
https://www.geek-share.com/detail/2672774638.html
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<map> #define mod 100000007 #define ll long long #define N 2005 using namespace std; int n,m,num,px ,py ; ll ans,t1,t2,t3,t4; typedef pair<int,int>pii; map<pii,bool>mp; void calc(int x,int y,int z){//计算顶点在正方形框架边,顶点上的正方形个数 z=min(z,x+y); if(!z)return; t1=(t1+1ll*(z+3)*z/2)%mod; if(z>x)t1=(t1-1ll*(z-x)*(z-x+1)/2)%mod; if(z>y)t1=(t1-1ll*(z-y)*(z-y+1)/2)%mod; } bool check(int x,int y){return x>=0&&x<=n&&y>=0&&y<=m;} void update(int x1,int y1,int x2,int y2){ if(!check(x1,y1)||!check(x2,y2))return; int res=0; if(mp[make_pair(x1,y1)])res++; if(mp[make_pair(x2,y2)])res++; t2++;t3+=res;if(res==2)t4++; } void solve(int x1,int y1,int x2,int y2){ int dx=x2-x1,dy=y2-y1; update(x1+dy,y1-dx,x2+dy,y2-dx); update(x1-dy,y1+dx,x2-dy,y2+dx); if (abs(dx+dy)&1) return; dy=(dx+dy)>>1; dx-=dy; update(x1+dx,y1+dy,x2-dx,y2-dy); } int main(){ #ifdef wsy freopen("data.in","r",stdin); #else //freopen(".in","r",stdin); //freopen(".out","w",stdout); #endif scanf("%d%d%d",&n,&m,&num); for(int i=1;i<=num;i++){ scanf("%d%d",&px[i],&py[i]); mp[make_pair(px[i],py[i])]=1; } for(int i=1;i<=min(n,m);i++) ans=(ans+1ll*(m-i+1)*(n-i+1)%mod*i%mod)%mod; for(int i=1;i<=num;i++){ calc(px[i],m-px[i],py[i]); calc(px[i],m-px[i],n-py[i]); calc(py[i],n-py[i],px[i]); calc(py[i],n-py[i],m-px[i]); t1=(t1-min(px[i],py[i]))%mod;//减去掉calc重复的方案 t1=(t1-min(px[i],n-py[i]))%mod; t1=(t1-min(m-px[i],py[i]))%mod; t1=(t1-min(m-px[i],n-py[i]))%mod; while(t1<0)t1+=mod; for(int j=1;j<i;j++)solve(px[i],py[i],px[j],py[j]); } t2%=mod;t3%=mod;t4%=mod; cout<<ans-t1+t2-t3/3+t4/6; return 0; }//?????
相关文章推荐
- [bzoj4558][JLoi2016]方【容斥原理】【计数】
- [BZOJ4558] [JLoi2016]方
- bzoj4558 [JLoi2016]方
- 【BZOJ】4558: [JLoi2016]方
- BZOJ4558 [JLoi2016]方
- Bzoj4558 [JLoi2016]方
- bzoj 4558: [JLoi2016]方 数学&计数
- [BZOJ4558][JLoi2016]方(数学相关+容斥原理)
- bzoj千题计划281:bzoj4558: [JLoi2016]方
- BZOJ 4558 [JLoi2016] 方
- BZOJ 4558|JLOI 2016|SHOI 2016|方|容斥原理
- BZOJ4558: [JLoi2016]方
- 【BZOJ 4558】 4558: [JLoi2016]方 (计数、容斥原理)
- 【JLOI2016】bzoj4558 方
- 4558: [JLoi2016]方
- bzoj 4559: [JLoi2016]成绩比较 dp+拉格朗日插值
- BZOJ 4559: [JLoi2016]成绩比较【计数dp,容斥,组合数
- [BZOJ4560][JLOI2016]字符串覆盖(贪心+DP)
- BZOJ 4560 [JLOI2016]字符串覆盖
- BZOJ 4561 [JLoi2016]圆的异或并 ——扫描线