zoukankan      html  css  js  c++  java
  • [SHOI 2017] 组合数问题

    [题目链接]

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

    [算法]

           回顾组合数的定义 :

           C(N , M)表示将N个小球放入M个盒子里的方案数

           我们发现题目要求的其实就是将nk个小球放入模k意义下于r个盒子中的方案数

           不妨设Fi , j表示放了i个小球 , j个盒子(模k意义下)的方案数

           有 : Fi , j = Fi - 1 , j - 1 + Fi - 1 , j

           矩阵乘法即可

           时间复杂度 : O(K ^ 3logNlogK)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e9 + 10;
    const int K = 55;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    
    int n , p , k , r;
    int mat[K][K];
    
    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 void multipy(int a[K][K] , int b[K][K])
    {
        static int res[K][K];
        for (int i = 0; i < k; ++i)
        {
            for (int j = 0; j < k; ++j)
            {
                res[i][j] = 0;
            }
        }
        for (int x = 0; x < k; ++x)
        {
            for (int i = 0; i < k; ++i)
            {
                for (int j = 0; j < k; ++j)
                {
                    res[i][j] = (res[i][j] + 1ll * a[i][x] * b[x][j] % p) % p;
                }
            }
        }
        for (int i = 0; i < k; ++i)
        {
            for (int j = 0; j < k; ++j)
            {
                a[i][j] = res[i][j];    
            }    
        }
    }
    inline void exp_mod(int mat[K][K] , ll n)
    {
        static int b[K][K];
        for (int i = 0; i < k; ++i)
        {
            for (int j = 0; j < k; ++j)
            {
                b[i][j] = (i == j);
            }
        }
        while (n > 0)
        {
            if (n & 1) multipy(b , mat);
            multipy(mat , mat);
            n >>= 1;
        }
        for (int i = 0; i < k; i++)
        {
            for (int j = 0; j < k; j++)
            {
                mat[i][j] = b[i][j];
            }
        }
    }
    
    int main()
    {
        
        read(n); read(p); read(k); read(r);
        for (int i = 0; i < k; ++i) 
        {
            ++mat[i][i]; 
            ++mat[i][((i - 1) % k + k) % k];
        }
        exp_mod(mat , (ll)n * k);
        printf("%d
    " , mat[r][0]);
        
        return 0;
    }
  • 相关阅读:
    Python3三位运算
    PyThon3函数的使用
    PyThon3类的基本使用
    PyThon3类的继承
    Python3方法重写
    【BZOJ3307】雨天的尾巴-线段树合并+树上差分
    【CF893F】Subtree Minimum Query-主席树
    【BZOJ2212】Tree Rotations(POI2011)-平衡树启发式合并
    【BZOJ2733】永无乡(HNOI2012)-平衡树启发式合并
    【BZOJ3160】万径人踪灭-FFT+Manacher
  • 原文地址:https://www.cnblogs.com/evenbao/p/10540113.html
Copyright © 2011-2022 走看看