HDU 5794 A Simple Chess (Lucas + dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794
多校这题转化一下模型跟cf560E基本一样,可以先做cf上的这个题。
题目让你求一个棋子开始在(1,1),只能像马一样走且往右下方走,不经过坏点,有多少种走法能到达(n,m)点。
比如n=6, m=5 有两个坏点,模型转换 如下图:
转换成简单模型之后,只要把棋子可能经过的坏点存到结构体中,按照x与y从小到大排序。
dp[i]表示从起点到第i个坏点且不经过其他坏点的方案数。
dp[i] = Lucas(x[i], y[i]) - sum(dp[j]*Lucas(x[i]-x[j], y[i]-x[j])) , x[j] <= x[i] && y[j] <= y[i] //到i点所有的路径数目 - 经过其他点的路径数目
那我们把最后一个点也设成坏点,比如dp[final],那么dp[final]就是答案了
1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <ctime> 10 #include <list> 11 #include <set> 12 #include <map> 13 using namespace std; 14 typedef long long LL; 15 typedef pair <LL, LL> P; 16 const int N = 1e2 + 5; 17 const LL mod = 110119; 18 struct data { 19 LL x, y; 20 bool operator <(const data& cmp) const { 21 return x == cmp.x ? y < cmp.y : x < cmp.x; 22 } 23 }q[N]; 24 LL f[mod + 5]; //阶乘 25 dp[N]; 26 27 LL Pow(LL a , LL n , LL mod) { 28 LL res = 1; 29 while(n) { 30 if(n & 1) 31 res = res * a % mod; 32 a = a * a % mod; 33 n >>= 1; 34 } 35 return res; 36 } 37 38 LL Comb(LL a , LL b , LL mod) { 39 if(a < b) { 40 return 0; 41 } 42 if(a == b) { 43 return 1; 44 } 45 return (f[a] * Pow(f[a - b]*f[b] % mod , mod - 2 , mod)) % mod; //乘法逆元 46 } 47 48 LL Lucas(LL n , LL m , LL mod) { 49 LL ans = 1; 50 while(m && n && ans) { 51 ans = (ans * Comb(n % mod , m % mod , mod)) % mod; 52 n /= mod; 53 m /= mod; 54 } 55 return ans; 56 } 57 58 bool judge(LL x, LL y) { //判断'马' 能否走到坏点 59 if(x > y) 60 swap(x, y); 61 LL dec = y - x; 62 if(dec > x || dec*2 > y || (x - dec) % 3 != 0 || (y - dec*2) % 3 != 0 || x - dec != y - dec*2) 63 return true; 64 return false; 65 } 66 67 P get(LL x, LL y) { //得到模型的x和y 68 P res; 69 if(x > y) { 70 LL dec = x - y; 71 res.first = dec, res.second = 0; 72 x -= dec * 2, y -= dec; 73 res.first += x / 3, res.second += y / 3; 74 } else { 75 LL dec = y - x; 76 res.first = 0, res.second = dec; 77 x -= dec, y -= dec * 2; 78 res.first += x / 3, res.second += y / 3; 79 } 80 return res; 81 } 82 83 int main() 84 { 85 int Case = 1; 86 LL n, m; 87 int k; 88 f[0] = 1; 89 for(LL i = 1; i <= mod; ++i) 90 f[i] = f[i - 1] * i % mod; 91 while(scanf("%lld %lld %d", &n, &m, &k) != EOF) { 92 n--, m--; 93 for(int i = 1; i <= k; ++i) { 94 scanf("%lld %lld", &q[i].x, &q[i].y); 95 q[i].x--, q[i].y--; 96 } 97 printf("Case #%d: ", Case++); 98 if(judge(n, m)) { 99 printf("0\n"); 100 continue; 101 } 102 P temp = get(n, m); 103 n = temp.first, m = temp.second; 104 int index = 0; 105 for(int i = 1; i <= k; ++i) { 106 if(judge(q[i].x, q[i].y)) 107 continue; 108 temp = get(q[i].x, q[i].y); 109 if(temp.first > n || temp.second > m) 110 continue; 111 q[++index].x = temp.first, q[index].y = temp.second; 112 } 113 sort(q + 1, q + index + 1); 114 q[++index].x = n, q[index].y = m; 115 memset(dp, 0, sizeof(dp)); 116 for(int i = 1; i <= index; ++i) { 117 LL sum = 0; 118 for(int j = 1; j < i; ++j) { 119 if(q[i].x >= q[j].x && q[i].y >= q[j].y) { 120 sum = (sum + dp[j]*Lucas(q[i].x - q[j].x - q[j].y + q[i].y, q[i].y - q[j].y, mod) % mod) % mod; 121 } 122 } 123 dp[i] = ((Lucas(q[i].x + q[i].y, q[i].y, mod) - sum) % mod + mod) % mod; 124 } 125 printf("%lld\n", dp[index]); 126 } 127 return 0; 128 }