黑暗

img

题目大意

\(n\) 个点,每个点一定是红,绿,蓝三种颜色之一。每一个点有一个出初始坐标 $ (x_i,y_i) $ 你要让每一个点都移动 \(m\) 步,每一步可以沿着 \(x\) 轴正负方向或者沿着 $ y $ 轴正负方向移动一个单位,即 \((x,y)\rightarrow\{(x+1,y),(x-1,y),(x,y+1),(x,y-1)\}\) 使得所有同色点在相同的位置上,不同色的点在不同的位置上,求方案数量。

题解

将坐标系旋转 \(45°\) ,将原来的 \((x,y)\rightarrow\{(x+1,y),(x-1,y),(x,y+1),(x,y-1)\}\) 变为 \((x,y)\rightarrow\{(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\n",res); return 0;
}

猜你喜欢

转载自www.cnblogs.com/OYJason/p/10052407.html