令
fi,j,k
表示第
i
个点通过加了
然后DP就很简单了
// BEGIN CUT HERE
// END CUT HERE
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <queue>
#include <assert.h>
#include <cstring>
#define pb push_back
#define fi first
#define se second
using namespace std;
const int N=510,P=1e9+9,NN=1000010;
int n,x,y;
int f[N][N][20],g[N][N][20],h[N][20];
int fac[NN],inv[NN];
struct Ps{
int x,y,v,f;
friend bool operator <(Ps a,Ps b){
return a.x<b.x || (a.x==b.x && a.y<b.y);
}
}a[N];
inline int C(int x,int y){
if(x<0 || y<0 || x<y) return 0;
return 1LL*fac[x]*inv[y]%P*inv[x-y]%P;
}
inline int calc(int x,int y,int tx,int ty,int k){
if(x>tx || y>ty) return 0;
if(x==tx && y==ty) return !k;
if(x==tx) return C(ty-y-1,k-1);
if(y==ty) return C(tx-x-1,k-1);
int ret=0;
for(int s=1;s<k;s++)
ret=(ret+1LL*C(k,s)*C(tx-x-1,s-1)%P*C(ty-y-1,k-s-1))%P;
return ret;
}
class NumberLabyrinthDiv1{
public:
int getNumberOfPaths(vector <int> X, vector <int> Y, vector <int> val, int xFinish, int yFinish, int K) {
x=xFinish; y=yFinish; n=0;
memset(h,0,sizeof(h));
memset(g,0,sizeof(g));
memset(f,0,sizeof(f));
for(int i=0;i<X.size();i++){
a[++n].x=X[i]; a[n].y=Y[i]; a[n].v=val[i];
}
a[++n].x=0; a[n].y=0; a[n].v=0; a[++n].x=x; a[n].y=y; a[n].v=0;
sort(a+1,a+1+n);
fac[0]=1; for(int i=1;i<=1000000;i++) fac[i]=1LL*fac[i-1]*i%P;
inv[1]=1; for(int i=2;i<=1000000;i++) inv[i]=1LL*(P-P/i)*inv[P%i]%P;
inv[0]=1; for(int i=1;i<=1000000;i++) inv[i]=1LL*inv[i]*inv[i-1]%P;
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++){
for(int k=0;k<=K;k++){
f[j][i][k]=calc(a[j].x+a[j].v,a[j].y,a[i].x,a[i].y,k);
if(a[j].v) f[j][i][k]=(f[j][i][k]+calc(a[j].x,a[j].y+a[j].v,a[i].x,a[i].y,k))%P;
}
}
for(int i=2;i<=n;i++)
for(int j=i-1;j;j--)
for(int k=0;k<=K;k++){
g[j][i][k]=f[j][i][k];
for(int s=j+1;s<i;s++){
for(int _k=0;_k<=k;_k++)
g[j][i][k]=(g[j][i][k]-1LL*g[j][s][_k]*calc(a[s].x,a[s].y,a[i].x,a[i].y,k-_k))%P;
}
}
for(int i=1;i<=n;i++)
for(int j=0;j<=K;j++) h[i][j]=g[1][i][j];
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
for(int k=0;k<=K;k++)
for(int s=0;s<=k;s++)
h[i][k]=(h[i][k]+1LL*h[j][s]*g[j][i][k-s])%P;
int p,ans=0;
for(int i=1;i<=n;i++)
if(a[i].x==x && a[i].y==y){
p=i; break;
}
for(int i=0;i<=K;i++) ans=(ans+h[p][i])%P;
return (ans+P)%P;
}
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); if ((Case == -1) || (Case == 5)) test_case_5(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arr0[] = {}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 3; int Arg4 = 3; int Arg5 = 2; int Arg6 = 2; verify_case(0, Arg6, getNumberOfPaths(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_1() { int Arr0[] = {}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 3; int Arg4 = 3; int Arg5 = 3; int Arg6 = 14; verify_case(1, Arg6, getNumberOfPaths(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_2() { int Arr0[] = {2}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {2}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {1}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 3; int Arg4 = 3; int Arg5 = 3; int Arg6 = 18; verify_case(2, Arg6, getNumberOfPaths(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_3() { int Arr0[] = {1, 3, 6}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {1, 3, 6}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {2, 2, 2}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 5; int Arg4 = 5; int Arg5 = 4; int Arg6 = 210; verify_case(3, Arg6, getNumberOfPaths(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_4() { int Arr0[] = {1, 19, 20, 21, 21, 21, 20, 19, 19}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {1, 11, 11, 11, 10, 9, 9, 9, 10}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {1, 2, 2, 2, 2, 2, 2, 2, 2}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 20; int Arg4 = 10; int Arg5 = 4; int Arg6 = 1778; verify_case(4, Arg6, getNumberOfPaths(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_5() { int Arr0[] = {13, 224, 77, 509, 1451, 43, 379, 142, 477}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {1974, 375, 38, 783, 3, 1974, 1790, 1008, 2710}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {30, 1845, 360, 11, 837, 84, 210, 4, 6704}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 509; int Arg4 = 2011; int Arg5 = 10; int Arg6 = 196052726; verify_case(5, Arg6, getNumberOfPaths(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main()
{
NumberLabyrinthDiv1 ___test;
___test.run_test(5);
system("pause");
}
// END CUT HERE