zoukankan      html  css  js  c++  java
  • Luogu 6162 [Cnoi2020]四角链

    (f(n, k))表示填(n)个格子,填了数字有(k)个的方案数,有初值(f(0, 0) = 1)
    不填第(n)个格子的方案数为(f(n - 1, k)),填第(n)个格子时,相当于从(n - (k - 1))个没用过的数中选一个出来填进去,方案数为((n - k + 1) * f(n - 1, k - 1))
    发现这个东西和第二类斯特林数的递推式很相似,打个表可以发现(f(n - 1, k) = S(n, n - k)),套上第二类斯特林数的公式,时间复杂度(O(nlogn))
    简单证明:

    [f(n - 1, k) = f(n - 2, k) + (n - k) * f(n - 2, k - 1) ]

    (m = n - k),

    [f(n - 1, n - m) = f(n - 2, n - m) + m * f(n - 2, n - m - 1) ]

    再令(f(n - 2, n - m - 1) = g(n, m)),

    [g(n + 1, m) = g(n, m - 1) + m * g(n, m) ]

    (这个地方有一些难懂,事实上(f)的两个参数都加1,(g)中的第二个参数是由(f)中的两个参数作差得到的,所以应当不变)
    (g)就是第二类斯特林数。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair <int, int> pin;
    
    const int N = 1e6 + 5;
    const int Maxn = 1e6;
    const ll P = 998244353LL;
    
    ll fac[N], ifac[N];
    
    template <typename T>
    inline void read(T &X) {
        char ch = 0; T op = 1; 
        for (X = 0; ch > '9' || ch < '0'; ch = getchar())
            if (ch == '-') op = -1;
        for (; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X * 10) + ch - '0';
        X *= op;
    }
    
    inline ll fpow(ll x, ll y) {
        ll res = 1;
        for (; y > 0; y >>= 1) {
            if (y & 1) res = res * x % P;
            x = x * x % P;
        }
        return res;
    }
    
    inline ll getc(ll n, ll m) {
        if (n < m) return 0LL;
        return fac[n] * ifac[m] % P * ifac[n - m] % P;
    }
    
    inline void inc(ll &x, ll y) {
        x += y;
        if (x >= P) x -= P;
    }
    
    inline void sub(ll &x, ll y) {
        x -= y;
        if (x < 0) x += P;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("sample.in", "r", stdin);
        clock_t st_clock = clock();
    #endif
    
        fac[0] = 1;
        for (int i = 1; i <= Maxn; i++) fac[i] = fac[i - 1] * i % P;
        ifac[Maxn] = fpow(fac[Maxn], P - 2);
        for (int i = Maxn - 1; i >= 0; i--) ifac[i] = ifac[i + 1] * (i + 1) % P;
        
        ll n, m, k, res = 0;
        read(n), read(k);
        m = n - k;
        for (int i = 0; i <= m; i++) {
            if (i & 1) sub(res, getc(m, i) * fpow(m - i, n) % P); 
            else inc(res, getc(m, i) * fpow(m - i, n) % P);
        }
        res = res * ifac[m] % P;
        printf("%lld
    ", res);
    
    #ifndef ONLINE_JUDGE
        clock_t ed_clock = clock();
        printf("time = %f ms
    ", (double)(ed_clock - st_clock) / CLOCKS_PER_SEC * 1000);
    #endif
        return 0;
    }
    
  • 相关阅读:
    富文本的使用
    sql
    # 多线程:为啥无法避免并发修改异常?(假设有两个线程,线程A,线程B),怎么避免并发修改异常?
    File&&字节流
    IO-字符流
    第二周疑问点
    异常
    常用API-Object+String
    学习JavaSE过程中的疑问点(第一周)
    JavaOOP
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/14477232.html
Copyright © 2011-2022 走看看