网上找了很多人的博客,都看不太懂,还是大力学长的方法好。

  要说明的一点是,因为是比较大的数字的组合数再加上mod比较小,因此用Lucas定理求组合数。

  代码如下(有注释):

  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <string.h>
  4 #include <set>
  5 #include <vector>
  6 using namespace std;
  7 const int mod = 110119;
  8 typedef long long ll;
  9 typedef pair<ll,ll> pii;
 10 
 11 int k;
 12 ll fact[120000+5],dp[100+5];
 13 ll n,m;
 14 vector<pii> V;
 15 
 16 void init()
 17 {
 18     fact[0] = fact[1] = 1;
 19     for(int i=2;i<=120000;i++) fact[i] = fact[i-1] * i % mod;
 20 }
 21 
 22 void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
 23 {
 24     if(!b) {d = a; x = 1; y = 0;}
 25     else
 26     {
 27         ex_gcd(b,a%b,y,x,d);
 28         y -= x * (a/b);
 29     }
 30 }
 31 
 32 ll qpow(ll a,ll b)
 33 {
 34     ll ans = 1;
 35     while(b)
 36     {
 37         if(b & 1) ans = ans * a % mod;
 38         a = a * a % mod;
 39         b >>= 1;
 40     }
 41     return ans;
 42 }
 43 
 44 ll inv(ll t,ll p)
 45 {
 46     /*ll x,y,d;
 47     ex_gcd(t,p,x,y,d);
 48     return d==1 ? (x%mod+mod)%mod : -1;*/
 49     return qpow(t,p-2);
 50 }
 51 
 52 int comb(int n,int m)
 53 {
 54     if(m<0 || n<m) return 0;
 55     return fact[n] * 1LL * inv(fact[m],mod) % mod * inv(fact[n-m],mod) % mod;
 56 }
 57 
 58 ll Lucas(ll n,ll m,int p)
 59 {
 60     return m ? Lucas(n/p,m/p,p) * comb(n%p,m%p) % mod : 1;
 61 }
 62 
 63 ll solve(int i,int j) // j to i 的无视障碍的步数总数
 64 {
 65     if(V[i].second < V[j].second || V[i].first < V[i].first || (V[i].first+V[i].second-V[j].first-V[j].second)%3) return -1;
 66     ll need = (V[i].first+V[i].second-V[j].first-V[j].second) / 3;
 67     // need 表示走过的步数
 68     ll step = Lucas(need, V[i].first-V[j].first-need, mod);
 69     // 第二个参数表示走过的两步的步数
 70     // 总的步数(need)中选择若干步是走两步的
 71     return step % mod;
 72 }
 73 
 74 int main()
 75 {
 76     init();
 77     int kase = 1;
 78     while(scanf("%I64d%I64d%d",&n,&m,&k)==3)
 79     {
 80         V.clear();
 81         for(int i=1;i<=k;i++)
 82         {
 83             ll x,y;scanf("%I64d%I64d",&x,&y);
 84             V.push_back(pii(x,y));
 85         }
 86         V.push_back(pii(1,1));
 87         V.push_back(pii(n,m));
 88         sort(V.begin(),V.end());
 89         memset(dp,0,sizeof(dp));
 90         int sz = V.size();
 91         for(int i=1;i<sz;i++)
 92         {
 93             dp[i] = solve(i,0);
 94             if(dp[i] == -1) dp[i] = 0;
 95             for(int j=0;j<i;j++)
 96             {
 97                 ll step = solve(i,j);
 98                 if(step != -1)
 99                 {
100                     dp[i] -= step * dp[j] % mod;
101                     // 所有从原点到i这个点的路径中,从原点到禁止点再从该禁止点到i点的所有路径都是不被允许的,需要减掉
102                     if(dp[i] < 0) dp[i] = ((dp[i] % mod) + mod) % mod;
103                 }
104             }
105         }
106         printf("Case #%d: %I64d\n",kase++,dp[sz-1]);
107     }
108 }