2016 多校 Multi-University Training Contest 6 A Simple Chess

来源:互联网 发布:公安大数据应用现状 编辑:程序博客网 时间:2024/05/21 10:40

hdu 5794 A Simple Chess

题意很简单,给你一个棋盘,和只能像国际象棋马的走法的棋子,棋子只能从11开始走 只能向斜下方走,棋盘上有写位置不能走,问你最后走到终点有几种走法。

凡事都从观察开始,棋盘很大,long long才能存,但是不能走的位置很少只有100,再结合题意,很明显的容斥,之后我们画图,找一些简单的情况分析,发现每个能去的位置都在一些平行的直线上,然后我们在把前几排的可行位置的方案数出来,发现刚好是一个斜过来的杨辉三角,这就意味着,这玩意的走法刚好是一个组合数,和普通的棋子走法类似,那么我们其实可以把他转换为普通的横着走和竖着走的棋子,将整个棋盘的坐标都进行转化,其实就是使坐标可以直接拿来算组合数。

到了这个时候,基本做法就已经出来了,容斥,组合数,取模,很明显,就是容斥+lucas。统计时,不重不漏的常用方法,就是有序化思想,这里也是一样,我们先定义一个dp

dp[i]表示走过第I个障碍,且不经过之前的障碍物的走法,这样子我们只需要对障碍物进行双关键字排序,按照顺序计算即可,具体转移方程见代码。

ps:这题坑了我很久,因为输入时就可以确定该棋盘是否无解,我在确认无解时直接跳出了,这样子不行,因为后面会有障碍物坐标的输入,而程序把他当做下一组数据的输入了,导致各种错.....


#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;typedef long long LL;bool flag;int sums;int cnt;LL n, m;LL h, w;LL a, b;LL fac[1000000];const LL MOD = 110119;struct node{LL x, y;LL sum;bool operator < (const node& n) const{return x < n.x || (x == n.x && y < n.y);}}pos[105];void init(){fac[0] = 1;for (LL i = 1; i <= MOD; i++)fac[i] = (fac[i - 1] * i) % MOD;}LL PowerMod(LL a, LL b, LL c){LL ans = 1;a %= c;while (b){if (b & 1)ans = (ans*a) % c;b >>= 1;a = (a*a) % c;}return ans;}LL comb(LL a, LL b, LL MOD){if (b > a) return 0;return fac[a] * PowerMod(fac[b] * fac[a - b], MOD- 2, MOD) % MOD;}LL lucas(LL n, LL m, LL MOD){LL ans = 1;while (n && m){ans = (ans * comb(n%MOD, m%MOD, MOD)) % MOD;n /= MOD;m /= MOD;}return ans;}int main(void){int cas = 1;init();while (~scanf("%lld%lld%d", &n, &m, &sums)){LL step;cnt = 0; flag = true;memset(pos, 0, sizeof pos);if ((n + m - 2) % 3 != 0) flag = false;if (flag){step = (n + m - 2) / 3 + 2;h = n - step + 2;w = step - h;if (h <= 0 || h >= step) flag = false;}LL tmp, ta, tb;for (int i = 0; i < sums; i++){scanf("%lld%lld", &a, &b);if (a == n && b == m){flag = false;continue;}if (!flag) continue;if ((a + b - 2) % 3 != 0) continue;tmp = (a + b - 2) / 3 + 2;ta = a - tmp + 2;tb = tmp - ta;if (ta <= 0 || ta >= tmp) continue;//if (ta > h || tb > w) continue;pos[cnt].x = ta;pos[cnt].y = tb;if (ta == 1 || tb == 1) pos[cnt++].sum = 1;else pos[cnt++].sum = lucas(ta + tb - 2, ta - 1, MOD) % MOD;}if (!flag){printf("Case #%d: 0\n", cas++);continue;}sort(pos, pos + cnt);pos[cnt].x = h;pos[cnt].y = w;pos[cnt].sum = lucas(h + w - 2, h - 1, MOD) % MOD;for (int i = 0; i <= cnt; i++){for (int j = 0; j < i; j++){if (pos[j].y > pos[i].y) continue;LL dx = pos[i].x - pos[j].x;LL dy = pos[i].y - pos[j].y;pos[i].sum = (pos[i].sum -  (pos[j].sum * lucas(dx + dy, dy, MOD) % MOD) + MOD) % MOD;}}printf("Case #%d: %lld\n", cas++, pos[cnt].sum);}return 0;}

1 0
原创粉丝点击