zoukankan      html  css  js  c++  java
  • [SCOI 2010] 字符串

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=1856

    [算法]

             不妨建立平面直角坐标系

             将“当前已经放了的字符”看作横坐标 , 1的个数与0的个数差看作纵坐标

             那么问题就转化为从(0 , 0)出发 , 每次向右上或右下移动一步 , 有多少条到达(n + m , n - m)且不经过直线y = -1的路径数

             考虑用总方案数 - 经过直线y = -1的路径数

             不难发现 , 总方案数为C(n + m , n)

             如何计算经过直线y = -1的路径数? 可以画图分析 , 由对称性可知 , 经过直线y = -1方案数等价于从(0 , -2) 走到(n + m , n - m)的方案数 , 为C(n + m , n - 1)

             答案即为C(n + m , n) - C(n + m , n - 1)

             预处理阶乘逆元即可

             时间复杂度 : O((N + M)logN)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define N 2000010
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int P = 20100403;
    
    int n , m;
    int fac[N] , inv[N];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline int exp_mod(int a , int n)
    {
            int res = 1 , b = a;
            while (n > 0)
            {
                    if (n & 1) res = 1ll * res * b % P;
                    b = 1ll * b * b % P;
                    n >>= 1;
            }
            return res;
    }
    inline int C(int x , int y)
    {
            if (x < y) return 0;
            return 1ll * fac[x] * inv[y] % P * inv[x - y] % P;
    }
    
    int main()
    {
            
            read(n); read(m);
            fac[0] = 1;
            for (int i = 1; i <= n + m; ++i) fac[i] = 1ll * fac[i - 1] * i % P;
            inv[n + m] = exp_mod(fac[n + m] , P - 2);
            for (int i = n + m - 1; i >= 0; --i) inv[i] = 1ll * inv[i + 1] * (i + 1) % P;
            printf("%d
    " , ((C(n + m , n) - C(n + m , n + 1)) % P + P) % P);
            
            return 0;
        
    }
  • 相关阅读:
    Linux 或 Windows 上实现端口映射
    请收藏,Linux 运维必备的 40 个命令总结,收好了~
    收藏:存储知识全面总结
    超详干货!Linux 环境变量配置全攻略
    iv012-LockSupport
    iv011-死锁编码及定位分析
    iv010-线程池
    iv009-Callable接口
    iv008-线程之间通信之生产者消费者
    iv007-synchronized和Lock的区别
  • 原文地址:https://www.cnblogs.com/evenbao/p/10623796.html
Copyright © 2011-2022 走看看