HDU5794 A Simple Chess

HDU5794 A Simple Chess

思路:

简单dp+组合数学

\[f_i表示起点到第i个障碍物不途径其他障碍物的方案数\\(起点视为0号,终点视为r+1号)\\ F(x,y)表示x点到y点的方案数\\ 显然易得f_i=F(0,i)-\sum_{x_j<x_i,y_j<y_i}f_jF(j,i)\\ 🐎步可看成(x+1,y+2)/(x+2,y+1)\\ 故可得总步数w=\frac{len(x,y)}{3}[不为整则F(x,y)为零]\\ 可由|x_x-x_y|得到(x+1,y+2)的次数,\\ 易得F(x,y)={x_y-x_x-w\choose w}\\ 然后便可轻易得到f\\ 显然答案为f_{r+1}\\ 时间复杂度O(Tr)\\ 细节详见代码 \]

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

#include<map>
#include<cmath>
#include<stack>
#include<deque>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
# define Type template<typename T>
# define ll long long
# define read read1<ll>()
Type T read1(){
    T t=0;char k;
    bool v=0;
    do (k=getchar())=='-'&&(v=1);while('0'>k||k>'9');
    while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
    return v?-t:t;
}
ll qkpow(ll n,ll x,ll mo){
    if(!x)return 1;
    ll t=qkpow(n,x>>1,mo);
    t=t*t%mo;
    if(x&1)t=t*n%mo;
    return t;
}
# define mod 110119ll
# define N 110118
ll fac[N+3],inv[N+3];
ll Ch(ll m,ll n){
    if(m<n)return 0;
    return fac[m]*inv[m-n]%mod*inv[n]%mod;
}
void init(){
    fac[0]=1;
    for(int i=1;i<=N;++i)
        fac[i]=fac[i-1]*i%mod;
    inv[N]=qkpow(fac[N],mod-2,mod);
    for(int i=N;i;--i)
        inv[i-1]=inv[i]*i%mod;
}
ll invi(ll x){return qkpow(x,mod-2,mod);}
ll lucas(ll m,ll n){
    if(n>m)return 0;
    if(m<mod)return Ch(m,n);
    return lucas(m/mod,n/mod)*Ch(m%mod,n%mod)%mod;
}
ll w[105];
pair<ll,ll>tx[105];
ll getw(ll n,ll m){
    if(n<0||m<0)return 0;
    ll w=n+m-2;
    if(w%3)return 0;
    w/=3;
    if(w>=n||w>=m)return 0;
    // cout<<w<<"----"<<n-w-1<<endl;
    return lucas(w,n-w-1);
}
int main(){
    init();
    ll n,m;int s;
    for(int T=1;~scanf("%lld %lld %d",&n,&m,&s);++T){
        for(int i=1;i<=s;++i)
            tx[i].first=read,tx[i].second=read;++s;
        tx[s].first=n,tx[s].second=m;
        sort(tx+1,tx+s+1);
        for(int i=1;i<=s;++i){
            w[i]=getw(tx[i].first,tx[i].second);
            // printf("w[%d]=%lld\n",i,w[i]);
            for(int j=1;j<i;++j)
                w[i]=(w[i]-w[j]*getw(tx[i].first-tx[j].first+1,tx[i].second-tx[j].second+1))%mod;
        }
        printf("Case #%d: %lld\n",T,(w[s]+mod)%mod);
    }
    return 0;
}
posted @ 2020-09-08 10:36  ファイナル  阅读(166)  评论(0)    收藏  举报