链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794
题意:一个n*m的木板,木板上有障碍物(不能走),现在要你算出从(1,1)到(n,m)有多少方案,只能按照这样的规则走:(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)=5 (x2>x1&&y2>y1).
分析:比赛的时候画图,发现是走到的点是杨辉三角,没有障碍物的时候每个点的方案数就是杨辉三角对应的值C(r-1,c-1)。
对于障碍物,我们可以用容斥来做,将起点终点与障碍物一起起算,设dp[i]表示第i个点作为终点的方案数,障碍物作为终点的方案数为:起点到他的方案数-(他之前除起点外的所有点作为终点的方案数*这些点作为起点到他的方案数)。 dp[i]=(dp[i]-dp[j]*solve(i,j)%mod+mod)%mod;
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1010
#define Mm 2000005
#define mod 110119
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
struct node {
ll x,y;
node(){}
node(ll x,ll y):x(x),y(y){}
bool operator <(const node a) const {
if(x==a.x) return y<a.y;
return x<a.x;
}
}p[200];
long long F[200010];
void init(long long p) {
F[0] = 1;
for(int i = 1;i <= p;i++)
F[i] = F[i-1]*i % (p);
}
long long inv(long long a,long long m){
if(a == 1)return 1;
return inv(m%a,m)*(m-m/a)%m;
}
long long Lucas(long long n,long long m,long long p){
if(n<0||m<0||m>n) return 0;
long long ans = 1;
while(n&&m)
{
long long a = n%p;
long long b = m%p;
if(a < b)return 0;
ans = ans*F[a]%p*inv(F[b]*F[a-b]%p,p)%p;
n /= p;
m /= p;
}
return ans;
}
ll solve(int i,int j) {
ll sx=p[j].x,sy=p[j].y;
ll ex=p[i].x,ey=p[i].y;
ll r=(ex-sx+ey-sy);
if(r%3||(sx>ex||sy>ey)) return 0;
r/=3;
ll c=ex-sx-r;
return Lucas(r,c,mod);
}
ll dp[200];
int main() {
ll n,m,a,b;
int k,cas=0;
init(mod);
while(~scanf("%I64d%I64d%d",&n,&m,&k)) {
for(int i=1;i<=k;i++) {
scanf("%I64d%I64d",&a,&b);
p[i]=node(a,b);
}
p[++k]=node(1,1);
p[++k]=node(n,m);
sort(p+1,p+k+1);
dp[1]=1;
for(int i=2;i<=k;i++) {
dp[i]=solve(i,1);
for(int j=2;j<i;j++) {
dp[i]=(dp[i]-dp[j]*solve(i,j)%mod+mod)%mod;
}
}
printf("Case #%d: %I64d\n",++cas,(dp[k]%mod+mod)%mod);
}
return 0;
}