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

HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)

时间:2016-08-05 12:02:42      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:

传送门

A Simple Chess

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 667    Accepted Submission(s): 168


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
(x2?x1)2+(y2?y1)2=5, x2>x1, y2>y1.<br>Unfortunately, there are some obstacles on the board. And the chess never can stay on the grid where has a obstacle.<br>I want you to tell me, There are how may ways the chess can achieve its goal. </div><div class=panel_bottom>&nbsp;</div><br><div class=panel_title align=left>Input</div> <div class=panel_content>The input consists of multiple test cases.<br>For each test case:<br>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.<br>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).</div><div class=panel_bottom>&nbsp;</div><br><div class=panel_title align=left>Output</div> <div class=panel_content>For each test case,output a single line &quot;Case #x: y&quot;, 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
 

Author
UESTC
 

Source

题目大意:
给一个 n?m 的方格,让你以象棋中”马”的方式从 (11) 点走到 (n,m)点的方法数对 MOD 取模,(“马”的方式只能向右上方),中间会有一些障碍。

解题思路:
卢卡斯定理加上容斥,(1,1) 点到 (n,m) 点,如果中间有 (x,y) 点的障碍的话,那么一定是(1,1) 点到 (n,m) 点的方法数 c ? (1,1) 点到 (x,y) 点的方法数 b ? (x,y) 点到 (n,m) 点的方法数 c。也就是 ans=c?a?b,中间会遇到很大的组合数取模的问题,也就是会用到卢卡斯定理(辅助手段)
My Code

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;

typedef long long LL;
const LL MOD = 110119LL;
struct Node
{
    LL x, y, s;
} node[105];

int cmp(const Node s1,const Node s2)
{
    if(s1.x==s2.x)
        return s1.y<s2.y;
    return s1.x<s2.x;
}

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[1000005];

void Get_Fact(LL p)
{
    fac[0]=1;
    for(int i=1; i<=p; i++)
        fac[i]=(fac[i-1]*i)%p;
}

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;
}

int main()
{
    LL n,m;
    int r;
    int Case=1;
    Get_Fact(MOD);
    while(scanf("%lld%lld%d",&n,&m,&r)!=EOF)
    {
        int tot=0;
        LL sum=0;
        int flag=0;
        if((n+m+1)%3==0)
        {
            LL s=(n+m+1)/3;
            if(n>=s&&m>=s)
            {
                LL t=n;
                n=2*s-m;
                m=2*s-t;
            }
            else
            {
                flag=1;
            }
        }
        else
        {
            flag=1;
        }
        for(int i=0; i<r; i++)
        {
            LL x,y;
            scanf("%lld%lld",&x,&y);
            if((x+y+1)%3==0)
            {
                LL s=(x+y+1)/3;
                if(x>=s&&y>=s)
                {
                    node[tot].x=2*s-y;
                    node[tot].y=2*s-x;
                    if(node[tot].x<=n&&node[tot].y<=m)
                        tot++;
                }
            }
        }
        if(flag==1)
        {
            printf("Case #%d: %lld\n",Case++,sum);
            continue;
        }
        if(tot>0)
            sort(node,node+tot,cmp);
        sum=Lucas(n+m-2,n-1,MOD)%MOD;
        for(int i=0; i<tot; i++)
        {
            node[i].s=Lucas(node[i].x+node[i].y-2,node[i].x-1,MOD)%MOD;
        }
        for(int i=0; i<tot; i++)
        {
            LL tt=Lucas(n-node[i].x+m-node[i].y,m-node[i].y,MOD);
            for(int j=i+1; j<tot; j++)
            {
                if(node[j].y>=node[i].y)
                {
                    LL d1=node[j].y-node[i].y;
                    LL d2=node[j].x-node[i].x;
                    node[j].s=(node[j].s-(node[i].s*Lucas(d1+d2,d1,MOD))%MOD)%MOD;
                }
            }
            sum=(sum-(node[i].s*tt)%MOD)%MOD;
            sum = (sum%MOD+MOD)%MOD;
        }
        printf("Case #%d: %lld\n",Case++,sum);
    }
}

HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)

标签:

原文地址:http://blog.csdn.net/qingshui23/article/details/52127322

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