zoukankan      html  css  js  c++  java
  • [BZOJ 4403] 序列统计

    [题目链接]

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

    [算法]

            令r - l + 1 = m

            若序列的长度为i , 那么每个数的出现次数x1 , x2 , x3 , .. xm满足 :

            x1 + x2 + x3 + .. + xm = n

            插板法 , (x1 , x2 , ... xm)共有C(i + m - 1 , m - 1)种组合

            那么问题就转化为了求 : C(m , m - 1) + C(m + 1 , m - 1) + ... + C(n + m - 1 , m - 1)

            在前面添一项C(m , m) 

            原式 = C(m , m) + C(m , m - 1) + C(m + 1 , m - 1) + ... + C(n + m - 1 , m - 1)

            一个经典的递推式 : C(n + 1 , m) = C(n , m - 1) + C(n , m)

            将原式相邻两项依次合并 , 原式 = C(n + m , m) - 1

            预处理阶乘逆元 , 卢卡斯定理求解模意义下的值 , 即可

            时间复杂度 : O(P) (P = 10 ^ 6 + 3)

    [代码]

              

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e9 + 10;
    const int P = 1e6 + 3; 
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    int fac[P + 1] , inv[P + 1];
    
    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 b = a , res = 1;
            while (n > 0)
            {
                    if (n & 1) res = 1ll * res * b % P;
                    b = 1ll * b * b % P;
                    n >>= 1;
            }
            return res;
    }
    inline void init()
    {
            fac[0] = 1;
            for (int i = 1; i <= P; i++) fac[i] = 1ll * fac[i - 1] * i % P;
            inv[P - 1] = exp_mod(fac[P - 1] , P - 2);
            for (int i = P - 2; i >= 1; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % P;
    }
    inline int C(int x , int y)
    {
            if (x < y) return 0;
            else return 1ll * fac[x] * inv[y] % P * 1ll * inv[x - y] % P;
    }
    inline int lucas(int n , int m)
    {
            if (n < m) return 0;
            if (n == m || !m) return 1;
            if (n < P && m < P) return C(n , m);
            else return 1ll * lucas(n / P , m / P) * C(n % P , m % P) % P;
    }
    
    int main()
    {
            
            int T;
            init();
            read(T);
            while (T--) 
            {
                    int n , l , r;
                    read(n); read(l); read(r);
                    printf("%d
    " , (lucas(n + r - l + 1 , r - l + 1) - 1 + P) % P);
            }
            
            return 0;
        
    }
  • 相关阅读:
    拟阵交
    HEOI2021退役记
    退役划水一
    上下界网络流学习笔记
    扩展卢卡斯学习笔记
    扩展中国剩余定理(EXCRT)学习笔记
    插头DP学习笔记
    如何优雅地生成仙人掌图
    Powerful Number 筛学习笔记
    边分治学习笔记
  • 原文地址:https://www.cnblogs.com/evenbao/p/10316845.html
Copyright © 2011-2022 走看看