题目大意
有 (n) 个点,每个点一定是红,绿,蓝三种颜色之一。每一个点有一个出初始坐标 $ (x_i,y_i) $ 你要让每一个点都移动 (m) 步,每一步可以沿着 (x) 轴正负方向或者沿着 $ y $ 轴正负方向移动一个单位,即 ((x,y) ightarrow{(x+1,y),(x-1,y),(x,y+1),(x,y-1)}) 使得所有同色点在相同的位置上,不同色的点在不同的位置上,求方案数量。
题解
将坐标系旋转 (45°) ,将原来的 ((x,y) ightarrow{(x+1,y),(x-1,y),(x,y+1),(x,y-1)}) 变为 ((x,y) ightarrow{(x+1,y+1),(x-1,y+1),(x+1,y-1),(x-1,y-1)}) 然后将 ((x,y))分开考虑,对于每一个确定的 $ x $ 或 $ y $ 和每一种颜色,求出所有该颜色来到这个坐标的方案数。
接着就容斥就好,答案 (=) 三种颜色集合点任意选 (-) 两个颜色在相同点另一个颜色任意选 (+ 2)三个点在相同颜色的方案数。
#include<bits/stdc++.h>
#define LL long long
#define M 3001
using namespace std;
int read(){
int nm=0,fh=1; char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
#define mod 1000000007
#define bas 3020
int n,m,C[1020][1020],X[M],Y[M],A,B,px[3][bas<<1|1],py[3][bas<<1|1];
int res,L[3],R[3],sumx[3],sumy[3],CX[8][bas<<1|1],CY[8][bas<<1|1];
int dtx[4],dty[4];
inline int add(int x,int y){return (x+y>=mod)?x+y-mod:x+y;}
inline int mns(int x,int y){return (x-y<0)?x-y+mod:x-y;}
inline int mul(int x,int y){return (LL)x*(LL)y%mod;}
const int STA[]={3,5,6,7};
int main(){
n=read(),A=read(),B=read(),m=read();
L[0]=1,L[1]=A+1,L[2]=A+B+1;
R[0]=A,R[1]=A+B,R[2]=n;
for(int i=0;i<=m;i++){
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j],C[i-1][j-1]);
}
for(int i=1,x,y;i<=n;i++) x=read(),y=read(),X[i]=x-y,Y[i]=x+y;
for(int pos=0;pos<=(bas<<1);pos++) for(int k=0;k<3;k++) px[k][pos]=py[k][pos]=1;
for(int pos=-bas;pos<=bas;pos++) for(int dis,k=0;k<3;k++){
for(int i=L[k];i<=R[k];i++){
dis=abs(X[i]-pos); if(dis>m||((dis^m)&1)){px[k][pos+bas]=0;break;}
px[k][pos+bas]=mul(px[k][pos+bas],C[m][(m-dis)>>1]);
} sumx[k]=add(px[k][pos+bas],sumx[k]);
for(int i=L[k];i<=R[k];i++){
dis=abs(Y[i]-pos); if(dis>m||((dis^m)&1)){py[k][pos+bas]=0;break;}
py[k][pos+bas]=mul(py[k][pos+bas],C[m][(m-dis)>>1]);
} sumy[k]=add(py[k][pos+bas],sumy[k]);
}
for(int i=0;i<=(bas<<1);i++) for(int sta=0,nowx=1,nowy=1;sta<4;sta++,nowx=nowy=1){
for(int k=0;k<3;k++) if((STA[sta]>>k)&1) nowx=mul(nowx,px[k][i]),nowy=mul(nowy,py[k][i]);
dtx[sta]=add(dtx[sta],nowx),dty[sta]=add(dty[sta],nowy);
} res=mul(mul(mul(sumx[0],sumy[0]),mul(sumx[1],sumy[1])),mul(sumx[2],sumy[2]));
res=mns(res,mul(mul(dtx[0],dty[0]),mul(sumx[2],sumy[2])));
res=mns(res,mul(mul(dtx[1],dty[1]),mul(sumx[1],sumy[1])));
res=mns(res,mul(mul(dtx[2],dty[2]),mul(sumx[0],sumy[0])));
res=add(res,mul(2,mul(dtx[3],dty[3]))),printf("%d
",res); return 0;
}