唔……突然发现最早打的两场(打的最烂的两场)没有写记录……(太烂所以不忍记录了吗。。。
还是把搞出来了的两道题记录一下吧= =勉强算弥补一下缺憾……
Round0 A
要求问(1,2)->(n-1,m) & (2,1)->(n,m-1)的不相交路径条数,蒟蒻当时只想到了$N^3$的DP……即枚举当前的总步数,以及两个人分别横向走了几步。
其实正解是(也只能是?)$O(N^2)$的!
ans=calc{(1,2)->(n-1,m)}*calc{(2,1)->(n,m-1)} - calc{(1,2)->(n,m-1)}*calc{(2,1)->(n-1,m)}
后面减去的那是啥呢?是两个人走到对方的目的地的总方案数……也就是两人路径交叉的方案数!将交叉的后半段交换一下,与两人走到各自的目的地,且路径发生交叉的方案一一对应!
(还是容斥原理?)
我比较傻逼,边界情况没有处理全2333……比如(n-1,m)和(n,m-1)走不到啊什么的……
1 //Round0 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=2010,mod=1e9+7; 20 /*******************template********************/ 21 int n,m,a[N][N]; 22 int f[N][N]; 23 char s[N]; 24 25 LL calc(int x1,int y1,int x2,int y2){ 26 memset(f,0,sizeof f); 27 f[x1][y1]=1; 28 F(i,x1,x2) F(j,y1,y2){ 29 if (a[i-1][j]) (f[i][j]+=f[i-1][j])%=mod; 30 if (a[i][j-1]) (f[i][j]+=f[i][j-1])%=mod; 31 } 32 return f[x2][y2]; 33 } 34 int main(){ 35 #ifndef ONLINE_JUDGE 36 freopen("A.in","r",stdin); 37 freopen("A.out","w",stdout); 38 #endif 39 n=getint(); m=getint(); 40 41 F(i,1,n){ 42 scanf("%s",s+1); 43 F(j,1,m) a[i][j]=s[j]=='0'; 44 } 45 // printf("%lld %lld %lld %lld\n",calc(1,2,n-1,m),calc(2,1,n,m-1),calc(1,2,n,m-1),calc(2,1,n-1,m)); 46 if (a[1][2] && a[2][1] && a[n-1][m] && a[n][m-1]) 47 printf("%lld\n",(calc(1,2,n-1,m)*calc(2,1,n,m-1)%mod-calc(1,2,n,m-1)*calc(2,1,n-1,m)%mod+mod)%mod); 48 else puts("0"); 49 return 0; 50 }