zoukankan      html  css  js  c++  java
  • 【AtCoder ABC 145 D】Knight

    题目大意:

      你现在在位置 $(0,0)$,每一次可以选择以下两种方式的任意一种移动:

    • 向下走一格,向右走两格;
    • 向下走两格,向下走一格。

      求可以到达 $(x,y)$ 的方案总数,对 $10^9+7$ 取模。

    解析:

      这道题给了一个很好的限制:只能向右、向下走。

      观察题目,可以发现如果 $3 mid x+y$,那么方案数是 $0$,因为每一次转移都会使得横纵坐标和加上 $3$。

      所以,我们只需列一个方程组,就可以求出向下走 $1$ 格并向右走 $2$ 格的方案次数,与向下走 $2$ 格且向下走 $1$ 格的方案次数。

      知道了分别转移的次数,我们就要枚举顺序。

      假设第一种方式转移 $a$ 次,第二种方式转移 $b$ 次。

      那么,问题就简化成这个样子:

        有 $a$ 个 $1$ 与 $b$ 个 $0$ 进行组合,可以制造出多少个不同的数字串 ?

      答案显而易见,是 $large{inom {a+b} a}$ 或 $large{inom {a+b} b}$。

      当然,要注意本题有取模,求组合数时要预处理逆元。

    代码:

    #include <cstdio>
    #define MOD 1000000007
    #define INF 1e9
    #define eps 1e-6
    typedef long long ll;
    
    ll x, y, xx, yy, inv[2000010], prod[2000010], ans;
    
    int main(){
    
        scanf("%lld%lld", &x, &y);
        if((x + y) % 3){
            puts("0");
            return 0;
        }
        xx = x - (x + y) / 3;
        yy = y - (x + y) / 3;
        if(x < 0 || y < 0)
            puts("0");
        else{
            inv[0] = inv[1] = 1;
            for(ll i = 2; i <= (xx + yy); i++)
                inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
            for(ll i = 2; i <= (xx + yy); i++)
                inv[i] = inv[i - 1] * inv[i] % MOD;
            prod[0] = 1;
            for(ll i = 1; i <= (xx + yy); i++)
                prod[i] = prod[i - 1] * i % MOD;
            ans = prod[xx + yy] * inv[xx] % MOD * inv[yy] % MOD;
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    linux系统如何发送邮件
    zabbix监测图形界面显示方框乱码解决方法
    Eclipse C++的配置问题launch failed binary not found
    Cpu表现出正弦曲线
    让cpu跑到100%的bat文件
    进程僵死
    华为一些笔试题~~~~零散总结
    数据库~~~投影与除操作
    C++连接Mysql数据库操作
    微软面试题目及答案
  • 原文地址:https://www.cnblogs.com/zengpeichen/p/11992399.html
Copyright © 2011-2022 走看看