UVALive - 6916 Punching Robot Lucas+dp

题目链接:

http://acm.hust.edu.cn/vjudge/problem/96344

Punching Robot

Time Limit: 1000MS
64bit IO Format: %lld & %llu

题意

在n*m的棋盘上有k个障碍物,并且这k个障碍物周围8个格子也都是障碍物,问从(1,1)到(n,m)总共有多少种不经过障碍物任何的走法(每次只能向下走或者向右走。

题解

这题和之前的一道题基本相同:点这里
由于给的质数比较小,所以不能保证互质(比如说mod与mod就不会互质了),所以求逆的时候会出问题,可以考虑求阶乘的时候单独把997这个因子全部提出来,并且记录下个数,单独讨论一下就可以做了。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=2e6+10;
const int mod=997;

int n,m,k;
LL dp[111],fac[maxn];
int num[maxn];
VPII robot;

void gcd(LL a,LL b,LL& d,LL& x,LL& y){
    if(!b){ d=a; x=1; y=0; }
    else{ gcd(b,a%b,d,y,x); y-=x*(a/b); }
}

LL Inv(LL a,int mod){
    LL d,x,y;
    gcd(a,mod,d,x,y);
    return d==1?(x+mod)%mod:-1;
}

LL get_C(int n,int m){
    if(n<m||n<0||m<0) return 0;
    if(num[n]!=num[m]+num[n-m]) return 0;
    return fac[n]*Inv(fac[m]*fac[n-m]%mod,mod)%mod;
}

LL calc(int i,int j){
    int n=robot[j].X-robot[i].X;
    int m=robot[j].Y-robot[i].Y;
    if(n<0||m<0) return 0;
    return get_C(n+m,n);
}

void pre(){
    clr(num,0);
    fac[0]=1;
    for(int i=1;i<maxn;i++){
        int x=i;
        num[i]+=num[i-1];
        while(x%mod==0){
            x/=mod;
            num[i]++;
        }
        fac[i]=fac[i-1]*x%mod;
    }
}

void init(){
    clr(dp,0);
    robot.clear();
}

int main() {
    pre();
    int tc,kase=0;
    scf("%d",&tc);
    while(tc--){
        scf("%d%d%d",&n,&m,&k);
        init();
        int su=1;
        for(int i=1;i<=k;i++){
            int x,y;
            scf("%d%d",&x,&y);
            for(int dx=-1;dx<=1;dx++){
                for(int dy=-1;dy<=1;dy++){
                    int a=x+dx,b=y+dy;
                    robot.pb(mkp(a,b));
                    if(a==1&&b==1||a==n&&b==m){
                        su=0;
                    }
                }
            }
        }
        if(!su){ puts("0"); continue; }
        robot.pb(mkp(1,1));
        robot.pb(mkp(n,m));
        sort(robot.begin(),robot.end());

        for(int i=1;i<robot.sz();i++){
            dp[i]=calc(0,i);
            for(int j=1;j<i;j++){
                dp[i]=(dp[i]-dp[j]*calc(j,i)%mod)%mod;
            }
            dp[i]=(dp[i]+mod)%mod;
        }
        printf("Case #%d: %lld\n",++kase,dp[robot.sz()-1]);
    }
    return 0;
}

//end-----------------------------------------------------------------------

其实直接上卢卡斯就不会有不互质的困扰啦!(跑的更快!)

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=2e6+10;
const int mod=997;

int n,m,k;
LL dp[111],fac[mod+10],facinv[mod+10],inv[mod+10];
VPII robot;

LL get_C(int n,int m){
    if(n<m||n<0||m<0) return 0;
    return fac[n]*facinv[n-m]%mod*facinv[m]%mod;
}

LL Lucas(LL n,LL m,LL p){
    if(m==0) return 1LL;
    return get_C(n%p,m%p)*Lucas(n/p,m/p,p)%p;
}

LL calc(int i,int j){
    int n=robot[j].X-robot[i].X;
    int m=robot[j].Y-robot[i].Y;
    if(n<0||m<0) return 0;
    return Lucas(n+m,n,mod);
}

void pre(){
    fac[0]=fac[1]=1;
    facinv[0]=facinv[1]=1,inv[1]=1;
    for(int i=2;i<mod;i++){
        fac[i]=fac[i-1]*i%mod;
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        facinv[i]=facinv[i-1]*inv[i]%mod;
    }
}

void init(){
    clr(dp,0);
    robot.clear();
}

int main() {
    pre();
    int tc,kase=0;
    scf("%d",&tc);
    while(tc--){
        scf("%d%d%d",&n,&m,&k);
        init();
        int su=1;
        for(int i=1;i<=k;i++){
            int x,y;
            scf("%d%d",&x,&y);
            for(int dx=-1;dx<=1;dx++){
                for(int dy=-1;dy<=1;dy++){
                    int a=x+dx,b=y+dy;
                    robot.pb(mkp(a,b));
                    if(a==1&&b==1||a==n&&b==m){
                        su=0;
                    }
                }
            }
        }
        if(!su){ puts("0"); continue; }
        robot.pb(mkp(1,1));
        robot.pb(mkp(n,m));
        sort(robot.begin(),robot.end());

        for(int i=1;i<robot.sz();i++){
            dp[i]=calc(0,i);
            for(int j=1;j<i;j++){
                dp[i]=(dp[i]-dp[j]*calc(j,i)%mod)%mod;
            }
            dp[i]=(dp[i]+mod)%mod;
        }
        printf("Case #%d: %lld\n",++kase,dp[robot.sz()-1]);
    }
    return 0;
}

//end-----------------------------------------------------------------------
posted @ 2016-09-03 01:02  fenicnn  阅读(204)  评论(0编辑  收藏  举报