题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794
题意:在一个有k个坏点的n*m的棋盘上走马,起点为(1,1),终点(n,m),每次可以从(x,y)走到(x+1,y+2)/(x+2,y+1),问有多少种不同的走法。
思路:如果从(x0,y0)到(x1,y1),没有任何坏点,有C( (x1-x0+y1-y0)/3 , x1-x0 - (x1-x0+y1-y0) )种方案,那么我们可以设f[i]为从起点,不经过任何坏点到达第i个坏点的路径数,然后把终点也加进坏点中,直接计算即可。f[i] = cal(i) - ∑f[j]*cal(j,i) ( j < i && xi>=xj && yi >= yj )。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define mod 110119
const int maxn = 200;
struct node
{
LL x,y;
LL tot;
}p[maxn];
bool cmp(node a,node b)
{
return a.x < b.x;
}
LL n,m,R;
LL f[120000],r[120000];
LL C(LL n,LL m){return n<m?0:f[n]*r[n-m]%mod*r[m]%mod;}
LL Lucas(LL n,LL m){
if(n<m||m<0)return 0;
if(!m||n==m)return 1;
return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
}
void init(){
int i;
for(r[0]=r[1]=f[0]=f[1]=1,i=2;i<mod;i++){
f[i]=f[i-1]*i%mod,r[i]=-r[mod%i]*(mod/i)%mod;
while(r[i]<0)r[i]+=mod;
}
for(i=2;i<mod;i++)r[i]=r[i]*r[i-1]%mod;
}
LL cal( LL x , LL y )
{
if ( (x+y) % 3 ) return 0;
if ( x == 0 && y == 0 ) return 1;
LL step = ( x + y ) / 3;
return Lucas( step ,x - step );
}
bool check()
{
if ( ( n + m ) % 3 != 0 ) return false;
rep(i,1,R)
if ( p[i].x == n && p[i].y == m ) return false;
return true;
}
int main()
{
init();
int kase = 0;
while( scanf("%I64d %I64d %I64d",&n,&m,&R)!=EOF )
{
n-- , m--;
rep(i,1,R)
{
scanf("%I64d %I64d",&p[i].x,&p[i].y);
p[i].x-- , p[i].y--;
}
printf("Case #%d: ",++kase);
if ( !check() )
{
puts("0");
continue;
}
sort(p+1,p+1+R,cmp);
R++;
p[R].x = n , p[R].y = m;
rep(i,1,R)
{
if ( ( p[i].x + p[i].y ) % 3 ) continue;
p[i].tot = cal( p[i].x , p[i].y );
rep(j,1,i-1)
if ( p[i].x > p[j].x && p[i].y > p[j].y )
p[i].tot = ( p[i].tot + mod - p[j].tot * cal( p[i].x - p[j].x , p[i].y - p[j].y ) % mod ) % mod;
}
printf("%I64d\n",p[R].tot);
}
return 0;
}