黑暗 - 容斥 - 組合計數
阿新 • • 發佈:2018-12-05
題目大意:平面上a個白色棋子,b個黃色,c個藍色,對每個棋子移動m步,每步可以上下左右移動1單位距離,問有多少種方案,使得任意兩點座標相同當且進當顏色相同。座標絕對值、棋子總數、步數均不超過1000。
題解:先容斥不同顏色座標不同,問題轉為一些點m步後走到同一個點的方案數,將(x,y)座標變換為(x+y,x-y),然後橫縱獨立,然後座標範圍不大,暴力列舉組合數計算即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 1000000007
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn() { int x;scanf("%d",&x);return x; }
const int N=100010;int fac[N],facinv[N],a[N];
inline int gabs(int x) { return x<0?-x:x; }
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k& 1)?ans=(lint)ans*x%mod:0;return ans; }
inline int prelude(int n)
{
rep(i,fac[0]=1,n) fac[i]=(lint)fac[i-1]*i%mod;
facinv[n]=fast_pow(fac[n],mod-2);
for(int i=n-1;i>=0;i--) facinv[i]=(i+1ll)*facinv[i+1]%mod;
return 0;
}
inline int binom(int n,int m) { if(n<0||m<0||n<m) return 0;return (lint)fac[n]*facinv[m]%mod*facinv[n-m]%mod; }
inline int calc(int *a,int n,int p,int m)
{
int ans=1;
rep(i,1,n)
{
int dx=gabs(a[i]-p);
if(((dx+m)%2)||dx>m) return 0;
ans=(lint)ans*binom(m,(dx+m)/2)%mod;
}
return ans;
}
inline int solve(vector<int> x,int n,int m)
{
rep(i,1,n) a[i]=x[i];int mn=a[1],mx=a[1];
rep(i,1,n) mn=min(mn,a[i]),mx=max(mx,a[i]);
lint ans=0;rep(i,mx-m,mn+m) ans+=calc(a,n,i,m);
return ans%mod;
}
struct P{
vector<int> x,y;int n;static int m;
inline int init(int _n)
{
n=_n,x.resize(n+1),y.resize(n+1);
rep(i,1,n) x[i]=inn(),y[i]=inn(),
x[i]+=y[i],y[i]=x[i]-2*y[i];
return 0;
}
inline P& operator=(const P &p) { x=p.x,y=p.y,n=p.n;return *this; }
inline P operator+(const P &p)const
{
P q;q.x=x,q.y=y,q.n=n+p.n;
rep(i,1,p.n) q.x.pb(p.x[i]),q.y.pb(p.y[i]);
return q;
}
inline int F()const { return (lint)solve(x,n,m)*solve(y,n,m)%mod; }
}A,B,C;
int P::m=0;
int main()
{
prelude(N-1);
int n=inn(),a=inn(),b=inn(),c=n-a-b;P::m=inn();
A.init(a),B.init(b),C.init(c),a=A.F(),b=B.F(),c=C.F();
int ab=(A+B).F(),bc=(B+C).F(),ac=(A+C).F(),abc=(A+B+C).F();
lint ans=(lint)a*b%mod*c%mod-(lint)ab*c%mod-(lint)ac*b%mod-(lint)bc*a%mod+2ll*abc%mod;
ans%=mod,ans+=mod,ans%=mod;return !printf("%lld\n",ans);
}