您的位置:首页 > 其它

BZOJ4558: [JLoi2016]方

2017-10-29 19:45 295 查看

n<=1e6 * m<=1e6的坐标系下求顶点不是指定的K<=2e3个点的正方形个数,%1e8+7.

一个基本的思路就是容斥,总-一个点+两个点-三个点+四个点。

总:把一个斜斜的正方形看成一个外接的正正的正方形,所以一个边长为d的正方形,顶点在他边上的正方形有d个,而边长为d的正方形在整个图上有(n-d+1)*(m-d+1)个,因此答案就是sigma d*(n-d+1)*(m-d+1)。

一个点:枚举点,先算经过他的正正的正方形:

1 #include<cstring>
2 #include<cstdlib>
3 #include<cstdio>
4 //#include<assert.h>
5 //#include<time.h>
6 #include<math.h>
7 //#include<queue>
8 #include<algorithm>
9 //#include<iostream>
10 using namespace std;
11
12 bool isdigit(char c) {return c>='0' && c<='9';}
13 int qread()
14 {
15     char c;int s=0,f=1;while (!isdigit(c=getchar())) f=(c=='-'?-1:1);
16     do s=s*10+c-'0'; while (isdigit(c=getchar())); return s*f;
17 }
18
19 int n,m,K;
20 const int mod=1e8+7;
21 int calc(int l,int r,int h)
22 {
23     h--;int x=min(l,r),y=max(l,r);
24     if (h<=x) return 1ll*(h+1)*h/2%mod;
25     if (h<=y) return (1ll*(x+1)*x/2%mod+1ll*(h-x)*x%mod)%mod;
26     if (h<x+y) return (1ll*(x+1)*x/2%mod+1ll*(y-x)*x%mod+1ll*(x-1+x-h+y)*(h-y)/2%mod)%mod;
27     return (1ll*(x+1)*x%mod+1ll*(y-x-1)*x%mod)%mod;
28 }
29 #define maxn 2011
30 int x[maxn],y[maxn];
31 #define maxh 10007
32 struct Hash
33 {
34     struct Node{int x,y,next;}list[maxh];int first[maxh],len;
35     Hash() {memset(first,0,sizeof(first));len=2;}
36     int hash(int x,int y)
37     {
38         return (1ll*x*19260817%maxh+1ll*y*19890604%maxh)%maxh;
39     }
40     void insert(int x,int y)
41     {
42         int v=hash(x,y);
43         list[len].x=x;list[len].y=y;
44         list[len].next=first[v];first[v]=len++;
45     }
46     int find(int x,int y)
47     {
48         if (x<0 || x>n || y<0 || y>m) return -2333;
49         int v=hash(x,y);
50         for (int i=first[v];i;i=list[i].next)
51         {
52             const Node &e=list[i];
53             if (e.x==x && e.y==y) return 1;
54         }
55         return 0;
56     }
57 }h;
58 int main()
59 {
60     n=qread(),m=qread(),K=qread();
61     int ans=0;
62     for (int i=1,to=min(n,m);i<=to;i++)
63         ans+=(1ll*i*(n-i+1)*(m-i+1)%mod),ans-=ans>=mod?mod:0;
64 //    cout<<ans<<endl;
65     for (int i=1;i<=K;i++)
66     {
67         x[i]=qread(),y[i]=qread();
68         int u=m-y[i],d=y[i],l=x[i],r=n-x[i];
69         ans-=min(u,l)+min(u,r)+min(d,l)+min(d,r),ans%=mod;
70 //    cout<<ans<<endl;
71         ans-=calc(l,r,u),ans%=mod;
72         ans-=calc(l,r,d),ans%=mod;
73         ans-=calc(u,d,l),ans%=mod;
74         ans-=calc(u,d,r),ans%=mod;
75 //    cout<<ans<<endl;
76         ans=(ans+mod)%mod;
77         h.insert(x[i],y[i]);
78     }
79 //    cout<<ans<<endl;
80     double dou=0;
81     for (int i=2;i<=K;i++)
82         for (int j=1;j<i;j++)
83         {
84 //            计算两个点的直的正方形和弯的正方形
85             int cnt;double tmp=0;
86             if ((cnt=h.find(x[i]-y[j]+y[i],y[i]+x[j]-x[i])+h.find(x[j]-y[j]+y[i],y[j]+x[j]-x[i]))==0)
87                 tmp+=1;
88             else if (cnt==1) tmp+=2.0/3.0;
89             else if (cnt==2) tmp+=0.5;else{}
90             if ((cnt=h.find(x[i]+y[j]-y[i],y[i]-x[j]+x[i])+h.find(x[j]+y[j]-y[i],y[j]-x[j]+x[i]))==0)
91                 tmp+=1;
92             else if (cnt==1) tmp+=2.0/3.0;
93             else if (cnt==2) tmp+=0.5;else{}
94             if (!((y[i]-y[j]+x[i]+x[j])&1) && !((x[j]-x[i]+y[i]+y[j])&1)
95             && !((x[i]+x[j]+y[j]-y[i])&1) && !((y[i]+y[j]+x[i]-x[j])&1))
96             if ((cnt=h.find((y[i]-y[j]+x[i]+x[j])/2,(x[j]-x[i]+y[i]+y[j])/2)+
97             h.find((x[i]+x[j]+y[j]-y[i])/2,(y[i]+y[j]+x[i]-x[j])/2))==0)
98                 tmp+=1;
99             else if (cnt==1) tmp+=2.0/3.0;
100             else if (cnt==2) tmp+=0.5;else{}else{}
101             dou+=tmp;
102         }
103     printf("%lld\n",((ans+((long long)floor(dou+1e-9))%mod)+mod)%mod);
104     return 0;
105 }
View Code  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: