AT2602 , Luogu

求对于 \(n\) 个数的排列 , 有多少种方案满足对于所有的 \(i\) , \(|P_i - i| != K\) , 答案对 \(924844033\) 取模 .

\(n,K \le 2000\)

设 \(g[i]\) 表示至少有 \(i\) 个数不满足题意的方案数 , 则 \(ans = \sum_{i=0}^n (-1)^{i} g[i]\) .

可以画一个二分图 , 左边表示下标 , 右边表示取值 , 相隔 \(K\) 格的左右连一条边 . 网上有一个图 :

对于每一条链 , 每个点只能连一条边 . 所以在每一条链上有转移 : 设 \(f[i][j][0/1]\) 表示选到第 \(i\) 个数 , 已经连了 \(j\) 条边 , \(i\) 与 \(i-1\) 是否连边的方案数 , 在链的内部转移 .

对于所有的链 , 可以拼接在一起 , 链之间也可以转移 \(f[i][j][0]\) 的方案数 , 这就相当于继承之前的结果继续 \(DP\) .

要特别注意的是 , 拼接的链的长度是 \(2n\) .

时间复杂度 \(O((2n)^2)\)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cassert>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
} const int N = 4005;
const int mod = 924844033; int a[N], g[N], f[N][N][2], fac[N];
int n, K, cnt, ans; inline int add(int x, int y){return (x+y)%mod;}
inline int dec(int x, int y){return (x-y+mod)%mod;}
inline int mul(LL x, int y){return x*y%mod;} int main(){
n = read(), K = read();
fac[0] = fac[1] = 1;
for(int i = 2; i <= n; ++i) fac[i] = mul(fac[i-1], i);
for(int i = 1; i <= K; ++i){
for(int j = i; j <= n; j += K)
a[++cnt] = j;
for(int j = i; j <= n; j += K)
a[++cnt] = j;
}
assert(cnt == (n << 1));
f[1][0][0] = 1;
for(int i = 2; i <= (n << 1); ++i){
for(int j = 0; j <= min(n, i/2); ++j){
f[i][j][0] = add(f[i-1][j][0], f[i-1][j][1]);
if(j > 0 && a[i] - a[i-1] == K) f[i][j][1] = f[i-1][j-1][0];
}
}
for(int i = 0; i <= n; ++i){
g[i] = add(f[n << 1][i][0], f[n << 1][i][1]);
if(!(i&1)) ans = add(ans, mul(g[i], fac[n - i]));
else ans = dec(ans, mul(g[i], fac[n - i]));
}
printf("%d\n", ans);
}

\(CF\) 上还有一篇讨论 , 是这题的 \(NTT\) 做法 : Solve AGC005D with NTT

[AT2062] ~K Perm Counting的更多相关文章

  1. [Agc005D]K Perm Counting

    [Agc005D] K Perm Counting Description 糟糕爷特别喜爱排列.他正在构造一个长度为N的排列.但是他特别讨厌正整数K.因此他认为一个排列很糟糕,当且仅当存在至少一个i( ...

  2. AGC 005 D - ~K Perm Counting

    D - ~K Perm Counting 链接 题意: 求有多少排列对于每个位置i都满足$|ai−i|!=k$.n<=2000 分析: 容斥+dp. $answer = \sum\limits_ ...

  3. 题解-Atcoder_agc005D ~K Perm Counting

    Problem AtCoder-agc005D 题意概要:给出\(n,k\),求合法的排列个数,其中合法定义为任何数字所在位置与自身值差的绝对值不为\(k\)(即求排列\(\{A_i\}\),使得\( ...

  4. AGC 005D.~K Perm Counting(容斥 DP 二分图)

    题目链接 \(Description\) 给定\(n,k\),求 满足对于所有\(i\),\(|a_i-i|\neq k\)的排列的个数. \(2\leq n\leq 2000,\quad 1\leq ...

  5. [AGC005D] ~K Perm Counting [dp]

    题面 传送门 思路 首先可以明确的一点是,本题中出现不满足条件的所有的数,都是分组的 只有模$K$意义下相同的数之间才会出现不满足条件的情况,而且仅出现在相邻的情况 那么我们考虑把这个性质利用起来 我 ...

  6. 【agc005d】~K Perm Counting

    题目大意 求有多少中1~n的排列,使得\(abs(第i个位置的值-i)!=k\) 解题思路 考虑容斥,\(ans=\sum_{i=0}^{n}(-1)^ig[i](n-i)!(g[i]表示至少有i个位 ...

  7. 一句话题解&&总结

    CF79D Password: 差分.两点取反,本质是匹配!最短路+状压DP 取反是套路,匹配是发现可以把操作进行目的化和阶段化,从而第二次转化问题. 且匹配不会影响别的位置答案 sequence 计 ...

  8. 做题记录 To 2019.2.13

    2019-01-18 4543: [POI2014]Hotel加强版:长链剖分+树形dp. 3653: 谈笑风生:dfs序+主席树. POJ 3678 Katu Puzzle:2-sat问题,给n个变 ...

  9. AtCoder Grand Contest 005

    AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...

随机推荐

  1. 15-Node.js学习笔记-Express的安装及检验

    最新的node已经把一些命令工具单独的分出来了,所以我们应该先下安装他的打包函数,再安装express,在进行检验就安装成功了 如需require还需在文件夹内单独安装 sudo npm instal ...

  2. 018_linux驱动之_阻塞和非阻塞

    阻塞操作     是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作. 被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足.   非阻塞操作   进程 ...

  3. js快速将字符串数组转化为数字数组(互换)

    1.数字数组转化为字符串数组 var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(String); //结果: ['1', '2', '3', '4', '5 ...

  4. CSP-S模拟68 题解

    T1: 不难想到贪心,但是怎么贪,他有两个限制条件,所以不是很好搞,所以用一个类似与wqs二分的思路我可能在口胡,因为你肯定要把最小的给删掉,所以你限定一个x或y,然后在选出另一个限制,所以要同时维护 ...

  5. c++示例 计算器

    #include <iostream> using namespace std; int main() { char op; float num1, num2; cout << ...

  6. csp-s模拟测试112 & csp-s模拟测试113

    考前两天模拟. Day1直接炸飞,T1浪费的时间太长,对拍+调试了一个多小时但复杂度还不能过,最后5分钟想出来了解决方案但是已经打不出来了.T2读入出了事故RE0.T3打了假贪心. Day2心态几乎也 ...

  7. 解决python在命令行中运行时导入包失败,出现错误信息 "ModuleNotFoundError: No module named ***"

    转自https://www.cnblogs.com/dreamyu/p/7889959.html https://www.cnblogs.com/lifeofershisui/p/8135702.ht ...

  8. Csdn账号如何注销?

    Csdn账号如何注销?   请在ios端app设置内注销 ios端注销在设置页面的底部左下角,andriod在2019.07月底更新,即可支持   文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎 ...

  9. VScode优化记录

      主题:   One Dark Pro VS Code 官网页面 这是为 VS Code准备的 One Dark 主题,他是 Atom 标志性的主题.需要我说更多吗?我喜欢这个主题.     Mon ...

  10. C之堆栈

    栈* 自动申请,自动释放* 大小固定,内存空间连续* 从栈上分配的内存叫静态内存 堆* 程序员自己申请* new/malloc* 大小取决于虚拟内存的大小,内存空间不连续* java中自动回收,C中需 ...