[AGC005D] ~K Perm Counting
Description
给出 n 和 k,求有多少个长度为 n 的排列 a 使得对于任意的 $ 1leqslant i leqslant n $ 都满足 ∣ai−i∣≠ k
数据范围:2⩽n⩽2000,1⩽k<n
Solution
显然容斥一波
剩下的回头补
#include<bits/stdc++.h> using namespace std; #define LL long long inline LL read() { LL f = 1 , x = 0; char ch; do { ch = getchar(); if(ch=='-') f=-1; } while(ch<'0'||ch>'9'); do { x=(x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch>='0'&&ch<='9'); return f*x; } const int MAXN = 4000 + 10; const int MOD = 924844033; int n,k; LL fac[MAXN]; LL dp[MAXN][MAXN][2],a[MAXN],tot; int main() { n = read(),k = read(); fac[0] = fac[1] = 1; for(int i=2;i<=n;i++) fac[i] = (fac[i-1] * i) % MOD; for(int i=1;i<=k;i++) { for(int j=i;j<=n;j+=k) a[++tot] = j; for(int j=i;j<=n;j+=k) a[++tot] = j; } dp[1][0][0] = 1; for(int i=2;i<=(n<<1);i++) { for(int j=0;j<=min(n,i/2);j++) { dp[i][j][0] = (dp[i-1][j][0] + dp[i-1][j][1]) % MOD; if(j&&(a[i]-a[i-1]==k)) dp[i][j][1] = (dp[i-1][j-1][0]); } } LL ans = 0; for(int i=0;i<=n;i++) { if(!(i&1)) ans = (ans + fac[n-i] * (dp[n<<1][i][0] + dp[n<<1][i][1]) % MOD) % MOD; else ans = (ans - (fac[n-i] * (dp[n<<1][i][0] + dp[n<<1][i][1])%MOD) + MOD) % MOD; } cout << ans << endl; }