您的位置:首页 > 其它

2016多校训练Contest6: 1002 A Simple Chess hdu5794

2016-08-04 23:53 399 查看
Problem Description

There is a n×m board,
a chess want to go to the position

(n,m) from
the position (1,1).

The chess is able to go to position (x2,y2) from
the position (x1,y1),
only and if only x1,y1,x2,y2 is
satisfied that (x2−x1)2+(y2−y1)2=5, x2>x1, y2>y1.

Unfortunately, there are some obstacles on the board. And the chess never can stay on the grid where has a obstacle.

I want you to tell me, There are how may ways the chess can achieve its goal.

Input

The input consists of multiple test cases.

For each test case:

The first line is three integers, n,m,r,(1≤n,m≤1018,0≤r≤100),
denoting the height of the board, the weight of the board, and the number of the obstacles on the board.

Then follow r lines,
each lines have two integers, x,y(1≤x≤n,1≤y≤m),
denoting the position of the obstacles. please note there aren't never a obstacles at position (1,1).

Output

For each test case,output a single line "Case #x: y", where x is the case number, starting from 1. And y is the answer after module 110119.

Sample Input

1 1 0
3 3 0
4 4 1
2 1
4 4 1
3 2
7 10 2
1 2
7 1


Sample Output

Case #1: 1
Case #2: 0
Case #3: 2
Case #4: 1
Case #5: 5


似乎数据特别水。。只要把不可到达的点删掉然后2^k容斥就可以直接过了。。并不明白怎么造的数据

正常的做法的话。。

我们用f[i]维护到某个障碍前面不经过任何障碍的方案数

然后转移的时候算出1,1到i的次数,

枚举1到i-1所有的障碍,乘走过中间部分的方案数,把这些减去

最后r+1加入终点

ans就是f[r+1]

这样复杂度是r^2的。

1,1到x,y的方案数,我们考虑马的走法,可以换成先往右下走一格,然后往右或者往下走。

因为总步数一定,所以可以组合数求解

拖了个lucas模版

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct obstacles
{
long long x,y;
bool operator <(obstacles z) const
{
return x<z.x||x==z.x&&y<z.y;
}
}a[1001];
long long f[1001];
long long mod=110119;
long long p1[1000001],p2[1000001];
inline long long PowMod(long long a,long long b)
{
long long ret=1;
while(b)
{
if(b&1)
ret=(ret*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ret;
}
long long fac[1000005];
inline long long Get_Fact(long long p)
{
fac[0]=1;
for(int i=1;i<=p;i++)
fac[i]=(fac[i-1]*i)%p;
}
inline long long Lucas(long long n,long long m,long long p)
{
long long ret=1;
while(n&&m)
{
long long a=n%mod,b=m%mod;
if(a<b) return 0;
ret=(ret*fac[a]*PowMod(fac[b]*fac[a-b]%p,p-2))%p;
n/=p;
m/=p;
}
return ret;
}
inline long long cale(int i,int j)
{
long long n=a[j].x-a[i].x,m=a[j].y-a[i].y;
if((m+n)%(long long)3!=0)
return 0;
long long step=(m+n)/(long long)3;
n-=step;
m-=step;
if(n<0||m<0)
return 0;
return Lucas(n+m,m,mod);
}
inline bool check(int i,int j)
{
if(a[i].x>a[j].x||a[i].y>a[j].y)
return false;
return true;
}
int main()
{
Get_Fact(mod);
int k=0;
long long n,m;
int r;
while(scanf("%I64d%I64d%d",&n,&m,&r)!=EOF)
{
k++;
int i,j;
for(i=1;i<=r;i++)
scanf("%I64d%I64d",&a[i].x,&a[i].y);
r++;
a[i].x=n;
a[i].y=m;
sort(a+1,a+1+r);
a[0].x=1;
a[0].y=1;
f[0]=1;
for(i=1;i<=r;i++)
{
f[i]=cale(0,i);
for(j=1;j<=i-1;j++)
{
if(check(j,i))
f[i]-=f[j]*cale(j,i)%mod;
while(f[i]<0)
f[i]+=mod;
}
}
printf("Case #%d: %I64d\n",k,f[r]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP 组合数