您的位置:首页 > 其它

HDU 5794 A Simple Chess (Lucas + dp)

2016-08-05 17:06 155 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794

多校这题转化一下模型跟cf560E基本一样,可以先做cf上的这个题。

题目让你求一个棋子开始在(1,1),只能像马一样走且往右下方走,不经过坏点,有多少种走法能到达(n,m)点。

比如n=6, m=5 有两个坏点,模型转换 如下图:

//#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
typedef pair <LL, LL> P;
const int N = 1e2 + 5;
const LL mod = 110119;
struct data {
LL x, y;
bool operator <(const data& cmp) const {
return x == cmp.x ? y < cmp.y : x < cmp.x;
}
}q
;
LL f[mod + 5]; //阶乘
dp
;

LL Pow(LL a , LL n , LL mod) {
LL res = 1;
while(n) {
if(n & 1)
res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}

LL Comb(LL a , LL b , LL mod) {
if(a < b) {
return 0;
}
if(a == b) {
return 1;
}
return (f[a] * Pow(f[a - b]*f[b] % mod , mod - 2 , mod)) % mod; //乘法逆元
}

LL Lucas(LL n , LL m , LL mod) {
LL ans = 1;
while(m && n && ans) {
ans = (ans * Comb(n % mod , m % mod , mod)) % mod;
n /= mod;
m /= mod;
}
return ans;
}

bool judge(LL x, LL y) { //判断'马' 能否走到坏点
if(x > y)
swap(x, y);
LL dec = y - x;
if(dec > x || dec*2 > y || (x - dec) % 3 != 0 || (y - dec*2) % 3 != 0 || x - dec != y - dec*2)
return true;
return false;
}

P get(LL x, LL y) { //得到模型的x和y
P res;
if(x > y) {
LL dec = x - y;
res.first = dec, res.second = 0;
x -= dec * 2, y -= dec;
res.first += x / 3, res.second += y / 3;
} else {
LL dec = y - x;
res.first = 0, res.second = dec;
x -= dec, y -= dec * 2;
res.first += x / 3, res.second += y / 3;
}
return res;
}

int main()
{
int Case = 1;
LL n, m;
int k;
f[0] = 1;
for(LL i = 1; i <= mod; ++i)
f[i] = f[i - 1] * i % mod;
while(scanf("%lld %lld %d", &n, &m, &k) != EOF) {
n--, m--;
for(int i = 1; i <= k; ++i) {
scanf("%lld %lld", &q[i].x, &q[i].y);
q[i].x--, q[i].y--;
}
printf("Case #%d: ", Case++);
if(judge(n, m)) {
printf("0\n");
continue;
}
P temp = get(n, m);
n = temp.first, m = temp.second;
int index = 0;
for(int i = 1; i <= k; ++i) {
if(judge(q[i].x, q[i].y))
continue;
temp = get(q[i].x, q[i].y);
if(temp.first > n || temp.second > m)
continue;
q[++index].x = temp.first, q[index].y = temp.second;
}
sort(q + 1, q + index + 1);
q[++index].x = n, q[index].y = m;
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= index; ++i) {
LL sum = 0;
for(int j = 1; j < i; ++j) {
if(q[i].x >= q[j].x && q[i].y >= q[j].y) {
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;
}
}
dp[i] = ((Lucas(q[i].x + q[i].y, q[i].y, mod) - sum) % mod + mod) % mod;
}
printf("%lld\n", dp[index]);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: