您的位置:首页 > 其它

BZOJ4558 [JLoi2016]方

2016-06-14 20:52 429 查看
KuribohG神犇说过,看到计数想容斥

尽管我在考场上也一直在默念这句话,但是并没有卵用,谁让我这么弱呢-_-

于是我们考虑考虑容斥,发现答案=随便选-sigma 以第i个坏点为顶点的正方形个数+sigma 同时以i,j为顶点的正方形个数-sigma 同时以i,j,k为顶点的正方形个数+sigma 同时以i,j,k,l为顶点的正方形个数

后三项可以枚举两个点,直接得出剩下两个点的位置,判断第3,4个点是否存在,是否合法来得到,判断是否存在可以用哈希

然而前两项怎么算啊-_-

随便选的我考场上找规律找出来了 ,然而只选一个点的考场上我就搞不出来了-_-

orz ljss,我们得到如下解法

对于一个边长为x的平行于坐标轴的正方形,四个顶点分别在这个正方形四条边上的正方形有x个,且这个边长为x的正方形边上的每个点都作为且仅作为那x个正方形中的一个正方形的顶点

这样的话,随便选的方案数就是sigma 边长为i的平行于坐标轴的正方形的个数×i,以i为顶点的方案数就是i在多少个平行于坐标轴的正方形上

就这么搞,把中间有些式子化简一下,就可以过了

哈希请手写链表哈希,jdfz的wfy神犇考场上用map被卡掉50分

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 2010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 100000007
#define eps 1e-8
ll n,m,K;
ll x[MAXN],y[MAXN];
ll ans;
ll tmp2,tmp3,tmp4;
vector<ll>hs[10000000];
ll cal1(ll x,ll y){
if(x>y){
return 0;
}
x--;
return ((1+y)*y/2-(1+x)*x/2+y-x)%MOD;
}
ll cal2(ll x,ll y,ll h,ll p){
if(x>y){
return 0;
}
return (y-x+1)*(h-p+1)%MOD;
}
ll cal3(ll x,ll y,ll p){
if(x>y){
return 0;
}
return (y-x+1)*p%MOD;
}
ll cal4(ll x,ll y,ll h){
if(x>y){
return 0;
}
x--;
return ((y-x)*h-(1+y)*y/2+(1+x)*x/2)%MOD;
}
ll cal(ll h,ll p,ll m){
ll re=0;
ll l=1,r=min(m,h);
re+=cal1(l,min(r,min(h-p+1,p-1)-1));
re+=cal2(max(h-p+1,l),min(p-1-1,r),h,p);
re+=cal3(max(p-1,l),min(h-p,r),p);
re+=cal4(max(l,max(h-p,p-2)+1),r,h);
return re%MOD;
}
bool jud(ll x,ll y){
return x>=1&&x<=n&&y>=1&&y<=m;
}
ll make_pair(ll x,ll y){
if(x<1||x>n||y<1||y>m){
return 0;
}
return (x-1)*m+y;
}
void push(ll x){
hs[x%10000000].push_back(x);
}
bool vis(ll x){
int i;
int X=x%10000000;
for(i=0;i<hs[X].size();i++){
if(hs[X][i]==x){
return 1;
}
}
return 0;
}
int main(){
int i,j,k;
scanf("%lld%lld%lld",&n,&m,&K);
n++;
m++;
for(i=1;i<=K;i++){
scanf("%lld%lld",&x[i],&y[i]);
x[i]++;
y[i]++;
push(make_pair(x[i],y[i]));
}
for(i=1;i<=min(n,m);i++){
(ans+=(n-i)*(m-i)%MOD*i%MOD)%=MOD;
}
for(i=1;i<=K;i++){
ll now=ans;
(ans+=MOD-cal(n,x[i],m-y[i]))%=MOD;
(ans+=MOD-cal(n,x[i],y[i]-1))%=MOD;
(ans+=MOD-cal(m,y[i],n-x[i]))%=MOD;
(ans+=MOD-cal(m,y[i],x[i]-1))%=MOD;
(ans+=min(x[i]-1,y[i]-1))%=MOD;
(ans+=min(n-x[i],y[i]-1))%=MOD;
(ans+=min(x[i]-1,m-y[i]))%=MOD;
(ans+=min(n-x[i],m-y[i]))%=MOD;
for(j=1;j<i;j++){
ll X=x[i]-x[j];
ll Y=y[i]-y[j];
if(jud(x[i]+Y,y[i]-X)&&jud(x[j]+Y,y[j]-X)){
(ans+=1)%=MOD;
tmp2++;
}
if(jud(x[i]-Y,y[i]+X)&&jud(x[j]-Y,y[j]+X)){
(ans+=1)%=MOD;
tmp2++;
}
if((x[i]-y[i]-x[j]+y[j])%2==0&&(y[j]-y[i]-x[i]+x[j])%2==0){
ll a=(y[j]-y[i]-x[i]+x[j])/2;
ll b=(x[i]-y[i]-x[j]+y[j])/2;
if(jud(x[i]+a,y[i]+b)&&jud(x[j]-a,y[j]-b)){
(ans+=1)%=MOD;
tmp2++;
}
if(vis(make_pair(x[i]+a,y[i]+b))&&jud(x[j]-a,y[j]-b)){
tmp3++;
}
if(jud(x[i]+a,y[i]+b)&&vis(make_pair(x[j]-a,y[j]-b))){
tmp3++;
}
if(vis(make_pair(x[i]+a,y[i]+b))&&vis(make_pair(x[j]-a,y[j]-b))){
tmp4++;
}
}
(tmp3+=vis(make_pair(x[i]+Y,y[i]-X))&&jud(x[j]+Y,y[j]-X))%=MOD;
(tmp3+=vis(make_pair(x[j]+Y,y[j]-X))&&jud(x[i]+Y,y[i]-X))%=MOD;
(tmp3+=vis(make_pair(x[i]-Y,y[i]+X))&&jud(x[j]-Y,y[j]+X))%=MOD;
(tmp3+=vis(make_pair(x[j]-Y,y[j]+X))&&jud(x[i]-Y,y[i]+X))%=MOD;
(tmp4+=(vis(make_pair(x[i]+Y,y[i]-X))&&vis(make_pair(x[j]+Y,y[j]-X)))+(vis(make_pair(x[i]-Y,y[i]+X))&&vis(make_pair(x[j]-Y,y[j]+X))))%=MOD;
}
}
/*
cout<<ans<<endl;
cout<<tmp2<<endl;
cout<<tmp3<<' '<<tmp3/3<<endl;
cout<<tmp4<<' '<<tmp4/6<<endl;
//*/
(ans+=(tmp4/6))%=MOD;
(ans+=MOD-tmp3/3)%=MOD;
printf("%lld\n",ans);
return 0;
}

/*
5 2 8
1 2
0 0
2 1
3 0
5 0
4 1
3 2
1 0

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