码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5794 A Simple Chess

时间:2016-08-05 23:07:53      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:

可以用总方案数减去经过障碍物的方案数。

先写一个判断某点是否可达的函数~ check(a,b)

再写一个某点到某点的方案数的函数~ cal(x1,x2,y1,y2)

设随便走 从(1,1)到(n,m)的方案数为P

设从(1,1)走到第i个障碍物并且不经过其余障碍物的方案数为num[i]。

那么 answer = P - sum{ num[i] * cal(x[i],y[i],n,m) }。

计算num[i] 可以将所有的障碍物按照x从小到大排个序,然后o(r*r)效率得到。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
inline int read()
{
    char c = getchar();  while(!isdigit(c)) c = getchar();
    int x = 0;
    while(isdigit(c)) { x = x * 10 + c - 0; c = getchar(); }
    return x;
}

LL mod=110119;

LL PowMod(LL a,LL b,LL MOD){
    LL ret=1;
    while(b){ if(b&1) ret=(ret*a)%MOD; a=(a*a)%MOD; b>>=1; }
    return ret;
}
LL fac[120000];

LL Lucas(LL n,LL m,LL p)
{
    LL ret=1;
    while(n&&m)
    {
        LL a=n%p,b=m%p;
        if(a<b) return 0;
        ret=(ret*fac[a]*PowMod(fac[b]*fac[a-b]%p,p-2,p))%p;
        n/=p, m/=p;
    }
    return ret;
}

bool check(LL a,LL b)
{
    if((a+b+1)%3!=0) return 0;
    LL f=(a+b+1)/3; f--;
    LL aa=a-f,bb=b-f;
    if(aa<=0||bb<=0) return 0;
    return 1;
}

LL cal(LL A,LL B,LL a,LL b)
{
    if(!check(a,b)) return 0;
    if(!check(A,B)) return 0;
    LL f,na,nb,nA,nB;
    f=(A+B+1)/3; f--; nA=A-f,nB=B-f;
    f=(a+b+1)/3; f--; na=a-f,nb=b-f;
    if(na-nA<0||nb-nB<0) return 0;
    return Lucas(nb-nB+na-nA,na-nA,mod);
}

LL N,M,r,num[110];
struct X { LL x,y; }s[110];
bool cmp(X a,X b){return a.x<b.x;}

int main()
{
    int cas=1;
    fac[0]=1; for(int i=1;i<=(int)mod;i++) fac[i]=(fac[i-1]*i)%mod;
    while(~scanf("%lld%lld%d",&N,&M,&r))
    {
        for(int i=1;i<=r;i++) scanf("%lld%lld",&s[i].x,&s[i].y);
        sort(s+1,s+1+r,cmp);
        printf("Case #%d: ",cas++);
        if(!check(N,M)) printf("0\n");
        else
        {
            LL ans=cal(1,1,N,M);
            for(int i=1;i<=r;i++)
            {
                num[i]=cal(1,1,s[i].x,s[i].y);
                for(int j=1;j<i;j++)
                    num[i]=(num[i]-num[j]*cal(s[j].x,s[j].y,s[i].x,s[i].y)%mod+mod)%mod;
            }
            for(int i=1;i<=r;i++) ans=(ans-num[i]*cal(s[i].x,s[i].y,N,M)%mod+mod)%mod;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

HDU 5794 A Simple Chess

标签:

原文地址:http://www.cnblogs.com/zufezzt/p/5742931.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!