HDU 5794 A Simple Chess

题目:A Simple Chess

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794

题意:起始点(1,1),要到达(n,m),下一步(x2,y2),这一步(x1,y1),需满足(x2-x1)^2 +(y2-y1)^2 = 5,且 x2>x1 、y2>y1。中间还有r 个障碍点,问最终有多少种方法到达(n,m)。n、m高达10^18,r最多100。

思路:

  

  大概画一下图,就可以知道从(1,1)到(n,m)的方法数是一个组合数。

  现在问题是障碍点,我们可以先计算(1,1)到每个障碍点的方法数sum(先当做这个障碍点不受其他障碍点影响),然后对障碍点排序,排序方法是从内圈到外圈( 其实可到达的点会形成无数的同心圆 ),然后两重循环,判断这个障碍点p1会对哪些障碍点(和终点)p2照成影响,受影响的障碍点sum减去影响数(p1.sum*组合数(这个组合数是从p1到p2的方法数)),逐层排查。就可以计算出(n,m)还剩下多少种方法可到达。

  难点就在于大组合数取模了...我事先也没有准备模板,临时盗用别人的。。

AC代码:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 using namespace std;
  5 #define N 150000
  6 typedef long long LL;
  7 struct Node
  8 {
  9   LL x,y,sum;
 10   bool friend operator < (Node a,Node b)
 11   {
 12     return a.x+a.y<b.x+b.y;
 13   }
 14 };
 15 const LL p=110119;
 16 LL fac[N];
 17 void init()
 18 {
 19     int i;
 20     fac[0] =1;
 21     for(i =1; i <= p; i++)
 22         fac[i] = fac[i-1]*i%p;
 23 }
 24 LL pow(LL a, LL b)
 25 {
 26     LL tmp = a % p, ans =1;
 27     while(b)
 28     {
 29         if(b &1)  ans = ans * tmp % p;
 30         tmp = tmp*tmp % p;
 31         b >>=1;
 32     }
 33     return  ans;
 34 }
 35 LL C(LL n, LL m)
 36 {
 37     if(m>n)return 0;
 38     return  fac[n]*pow(fac[m]*fac[n-m],p-2)%p;
 39 }
 40 LL cfun(LL n, LL m)
 41 {
 42     if(m ==0)  return 1;
 43     else return  (C(n%p,m%p)*cfun(n/p, m/p))%p;
 44 }
 45 Node a[110];
 46 int ao;
 47 
 48 bool check(Node a,Node b)
 49 {
 50   if( (b.x+b.y-a.x-a.y) % 3 != 0 ) return false;
 51   LL t=b.y-a.y;
 52   if(b.x-a.x<=2*t && 2*(b.x-a.x) >=t ) return true;
 53   return false;
 54 }
 55 LL solve(Node a,Node b)
 56 {
 57   if(b.x==a.x && b.y==a.y) return a.sum;
 58   if( !check(a,b) ) return 0;
 59   LL xia=(b.x+b.y-a.x-a.y)/3;
 60   LL shang=(b.y-a.y)-xia;
 61   return (a.sum*cfun(xia,shang))%p;
 62 }
 63 
 64 int main()
 65 {
 66   init();
 67   LL n,m;
 68   int r,cas=1;
 69   while(scanf("%I64d%I64d%d",&n,&m,&r)!=EOF)
 70   {
 71     Node s,t;
 72     s.sum=1;
 73     s.x=0,s.y=0;
 74     n--,m--;
 75     t.x=n,t.y=m;
 76     t.sum=solve(s,t);
 77     ao=0;
 78     for(int i=0;i<r;i++)
 79     {
 80       scanf("%I64d%I64d",&a[ao].x,&a[ao].y);
 81       a[ao].x--,a[ao].y--;
 82       if( !check(s,a[ao]) ) continue;
 83       ao++;
 84     }
 85     for(int i=0;i<ao;i++)
 86     {
 87       a[i].sum=solve(s,a[i]);
 88     }
 89     sort(a,a+ao);
 90     for(int i=0;i<ao;i++)
 91     {
 92       for(int j=i+1;j<ao;j++)
 93       {
 94         if( check(a[i],a[j]) )
 95         {
 96           a[j].sum=(a[j].sum-solve(a[i],a[j])+p)%p;
 97         }
 98       }
 99       t.sum=(t.sum-solve(a[i],t)+p)%p;
100     }
101     printf("Case #%d: ",cas++);
102     printf("%I64d
",t.sum);
103   }
104   return 0;
105 }
原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5740838.html