zoukankan      html  css  js  c++  java
  • AGC 005 D

    D - ~K Perm Counting

    链接

    题意:

      求有多少排列对于每个位置i都满足$|aii|!=k$。n<=2000

    分析:

      容斥+dp。

      $answer = sumlimits_{i = 0}^{n}(-1)^ig[i] imes (n - i)!$

      $g[i]$表示至少存在I个位置满足$a[i] - i = k$个数。

      考虑如何求出$g[]$。 如果建立两列点,一个表示数字,一个表示下标,左边第i个点与右边第i-k和i+k个点连边,那么这是一张二分图,g[i]就是求满足有刚好i个匹配的方案数。

      发现这样图可以按照模k的余数分成2k条链,每条链互不影响,链内满足不能有相邻的一起选。于是可以$f[i][j][0]$表示到链上的第i个位置,当前有j个匹配,第i个选不选的方案数。

      考虑如何将2k条链合并:因为链与链之间是互不影响的,所以可以建立一个点,连接两条链,然后让这个点一定不选即可。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 4005, mod = 924844033;
    int f[N][N][2], g[N], A[N], fac[N];
    
    inline void add(int &x,int y) { x += y; if (x >= mod) x -= y; }
    
    int main() {
        int n = read(), k = read(), Ans = 0;
        int cnt = 0;
        for (int i = 1; i <= k; ++i) {
            for (int j = i; j <= n; j += k) A[++cnt] = (i == j);
            for (int j = i; j <= n; j += k) A[++cnt] = (i == j);
        }
        f[0][0][0] = 1;
        for (int i = 1; i <= (n << 1); ++i) 
            for (int j = 0; j <= i; ++j) {
                add(f[i][j][0], (f[i - 1][j][0] + f[i - 1][j][1]) % mod);
                if (!A[i] && j) add(f[i][j][1], f[i - 1][j - 1][0]);
            }
        fac[0] = 1;
        for (int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % mod;
        for (int i = 0; i <= n; ++i) {
            int res = (f[n << 1][i][0] + f[n << 1][i][1]) % mod;
            Ans += 1ll * (i & 1 ? -1 : 1) * res * fac[n - i] % mod;
            Ans = (Ans % mod + mod) % mod;
        }
        cout << Ans;
        return 0;
    }
  • 相关阅读:
    java生成4个不同的随机数
    前端学习(三十二)正则(笔记)
    前端学习(三十一)canvas(笔记)
    前端学习(三十)es6的一些问题(笔记)
    前端学习(二十九)nodejs(笔记)
    前端学习(二十八)es6&ajax(笔记)
    前端学习(二十七)存储&es6(笔记)
    前端学习(二十七)自动构造工具交互(笔记)
    前端学习(二十六)移动端s(笔记)
    前端学习(二十四)一些总结(笔记)
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10336625.html
Copyright © 2011-2022 走看看