• UVALive 6916 Punching Robot dp


    Punching Robot

    题目连接:

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4928

    Description

    In this problem, you are given a grid map of N ×M (N rows and M
    columns) where the rows are numbered 1. . . N from top to bottom,
    and the columns are numbered 1. . . M from left to right. Your task
    is to count in how many ways you can reach cell (N, M) from cell
    (1, 1) given that you are only allowed to move right or downward
    at any time, i.e. if your current location is at cell (r, c), then you
    can only move to cell (r + 1, c) or (r, c + 1). However, we quickly
    realized that this kind of problem could be too easy for you, thus,
    not challenging. Therefore, we decided to put K punching robots
    in the map. Each punching robot is able to punch any object which
    lies in any of 3×3 cells centered at the robot (Figure 1). To simplify
    the problem, you may assume that the punching areas of any robot
    do not overlap.
    Your (new) task is: count in how many ways you can reach cell (N, M) from cell (1, 1) without
    being punched by any robot, given that you are only allowed to move right or downward at any time.
    As the output can be very large, you need to modulo the output by 997. For example, consider the
    following map of 4 x 10 with two punching robots at (3, 3) and (2, 8).
    Figure 2.
    In this example, there are 4 ways to reach (4, 10) from (1, 1) without being punched by any of the
    robots. All those 4 paths only differ when they go from (1, 5) to (4, 6):
    • . . . , (1, 5), (1, 6), (2, 6), (3, 6), (4, 6), . . .
    • . . . , (1, 5), (2, 5), (2, 6), (3, 6), (4, 6), . . .
    • . . . , (1, 5), (2, 5), (3, 5), (3, 6), (4, 6), . . .
    • . . . , (1, 5), (2, 5), (3, 5), (4, 5), (4, 6),
    Meanwhile, there is only one unique path from (1, 1) to (1, 5) and from (4, 6) to (4, 10).

    Input

    The first line of input contains an integer T (T ≤ 100) denoting the number of cases. Each case begins
    with three integers: N, M, and K (2 ≤ N, M ≤ 1, 000, 000; 0 ≤ K ≤ 10) denoting the size of the map
    and the number of punching robots respectively. The following K lines, each contains two integers: Ri
    and Ci (1 < Ri < N; 1 < Ci < M) denoting the position of i-th robot (row and column respectively)
    in the map. You are guaranteed that, for any two robots, the row difference or the column difference
    will be at least 3, i.e. no two robots’ punching areas are overlapping. You are also guaranteed that cell
    (1, 1) and cell (N, M) are not in punching areas of any robots.

    Output

    For each case, output ‘Case #X: Y ’, where X is the case number starts from 1 and Y is the answer
    for that case modulo by 997.
    Explanation for 2nd sample case:
    The following figure represents the map for the 2nd sample
    case.
    As you can see, there is no way you can reach (3, 5) from (1,

    1. without being punched by the robot.

    Sample Input

    4
    4 10 2
    3 3
    2 8
    3 5 1
    2 3
    5 5 0
    10 9 3
    9 3
    6 8
    3 4

    Sample Output

    Case #1: 4
    Case #2: 0
    Case #3: 70
    Case #4: 648

    Hint

    题意

    给你个(n,m)的方格,里面有一些坏的3*3位置,问你从(1,1)到(n,m)的方案数是多少

    题解:

    我们把3*3的拆成9个坏点,那么这道题就和CF的某道题一样了

    http://www.cnblogs.com/qscqesze/p/4669136.html

    但是这道题的模数是997,所以取逆元的时候可能有问题,你需要把997单独拿出来讨论一下就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 3000005
    #define mod 997
    typedef long long ll;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int cas=0;
    struct Point
    {
        long long x,y;
    }points[maxn];
    bool cmp(Point a,Point b)
    {
        if(a.x==b.x)
            return a.y<b.y;
        return a.x<b.x;
    }
    ll p=mod;
    ll fac[maxn],num[maxn];
    ll qpow(ll a,ll b)
    {
        ll ans=1;a%=mod;
        for(ll i=b;i;i>>=1,a=a*a%mod)
            if(i&1)ans=ans*a%mod;
        return ans;
    }
    ll C(ll n,ll m)
    {
        if(m>n||m<0)return 0;
        if(num[n]!=num[n-m]+num[m]) return 0;
        ll s1=fac[n],s2=fac[n-m]*fac[m]%mod;
        return s1*qpow(s2,mod-2)%mod;
    }
    ll f[maxn];
    int main()
    {
        fac[0]=1;
        for(int i=1;i<maxn;i++)
        {
            if(i%997!=0)
                fac[i]=fac[i-1]*i%mod,num[i]=num[i-1];
            else
            {
                num[i]=num[i-1];
                int tmp=i;
                while(tmp%997==0)
                    num[i]++,tmp/=997;
                fac[i]=fac[i-1]*tmp;
            }
        }
        int t;scanf("%d",&t);
        while(t--){
            int n=read(),m=read(),k=read();
            for(int i=1;i<=k;i++)
            {
                points[i*9-8].x=read();
                points[i*9-8].y=read();
                points[i*9-8].x-=1;
                points[i*9-8].y-=1;
    
                points[i*9-7].x=points[i*9-8].x-1;
                points[i*9-7].y=points[i*9-8].y-1;
    
                points[i*9-6].x=points[i*9-8].x;
                points[i*9-6].y=points[i*9-8].y-1;
    
                points[i*9-5].x=points[i*9-8].x+1;
                points[i*9-5].y=points[i*9-8].y-1;
    
                points[i*9-4].x=points[i*9-8].x-1;
                points[i*9-4].y=points[i*9-8].y;
    
                points[i*9-3].x=points[i*9-8].x+1;
                points[i*9-3].y=points[i*9-8].y;
    
                points[i*9-2].x=points[i*9-8].x-1;
                points[i*9-2].y=points[i*9-8].y+1;
    
                points[i*9-1].x=points[i*9-8].x;
                points[i*9-1].y=points[i*9-8].y+1;
    
                points[i*9].x=points[i*9-8].x+1;
                points[i*9].y=points[i*9-8].y+1;
            }
            k*=9;
            points[++k].x=n-1;
            points[k].y=m-1;
            sort(points+1,points+k+1,cmp);
            for(int i=1;i<=k;i++)
            {
                f[i]=C(points[i].x+points[i].y,points[i].x);
                for(int j=1;j<i;j++)
                {
                    if(points[j].y<=points[i].y)
                    {
                        f[i]+=(p-f[j]*C(points[i].x-points[j].x+points[i].y-points[j].y,points[i].x-points[j].x)%p);
                        f[i]%=p;
                    }
                }
            }
            printf("Case #%d: %lld
    ",++cas,f[k]%p);
        }
    }
  • 相关阅读:
    【剑指Offer】34、第一个只出现一次的字符
    【剑指Offer】33、丑数
    【剑指Offer】32、把数组排成最小的数
    linux精彩收集
    shell-总结【摘录】
    linux -特殊符号
    linux --mount
    linux--lsof
    linux--find
    Linux之rsync数据同步服务
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5734167.html
Copyright © 2020-2023  润新知