• 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
    ");
    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
    ", dp[index]);
    126     }
    127     return 0;
    128 }
    View Code
  • 相关阅读:
    docker 安装redis
    docker安装mongodb
    最强NBA
    在IDEA中配置RunDashboard
    【给每个人的摄影史33】普通人如何通过摄影史提升拍摄水平:长线学习的建议
    【给每个人的摄影史32】普通人如何通过摄影史提升拍摄水平:拍摄层面的提示
    【给每个人的摄影史31】普通人如何通过摄影史提升拍摄水平:意识上的提示
    【给每个人的摄影史30】普通人如何通过摄影史提升拍摄水*:再次回顾摄影史
    【给每个人的摄影史29】通过读画册培养摄影眼
    【给每个人的摄影史27】用照片表达观念艺术:作为照片的观念艺术
  • 原文地址:https://www.cnblogs.com/Recoder/p/5742082.html
Copyright © 2020-2023  润新知