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

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  (x2x1)2+(y2y1)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,(1n,m1018,0r100) , 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(1xn,1ym) , 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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值