题面

传送门

思路

首先可以明确的一点是,本题中出现不满足条件的所有的数,都是分组的

只有模$K$意义下相同的数之间才会出现不满足条件的情况,而且仅出现在相邻的情况

那么我们考虑把这个性质利用起来

我们单独把其中一组抽出来考虑:设这一组为$p,p+k,p+2k,p+3k.....$

那么我们发现,这其中每两个相邻的数之间都是互相不能选的

但是要注意,我们本题中讨论的实际上更应该是位置的关系,所以此时就变成了这样的形式:

位置$p+ki$不能选数$p+k(i+1)$,位置$p+ki(i+1)$不能选数$p+ki$

也就是说这两条边是交叉的

我们考虑对于每个值构建两个点,一个代表顺序为这个值的位置,一个代表这个数

那么上述的同一组的数中,我们连接不能同时选的数和位置,可以构造出两条链:

数$p$---位置$p+k$---数$p+2k$---位置$p+3k$......

位置$p$---数$p+k$---位置$p+2k$---数$p+3k$......

这两条链上的选择又是互相独立的

于是,我们把一个链单独拿出来考虑

显然这个链上选择了几条边,就有几个点是不满足要求的

那么我们可以通过一个$dp[i][j][0/1]$表示前$i$个点选了$j$条边,目前最后一条边选了没有(因为这里不能两条相邻的边同时选),来推出这条链选每一个数量的边的方案数量

(方程参见代码)

同时本题中有一个显然的组合容斥:

设$ans$为答案,那么$ans=\sum_{i=0}^n method(i)(-1)^i (n-i)!$,其中$method(i)$表示选$i$条边的方案数

那么我们只要把所有的链拼起来(不同的链的连接位置强制不能选边),然后跑$dp$算答案就可以了

感觉讲的不是很清楚......具体可以参考代码的注释

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#define ll long long
#define MOD 924844033
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,k;
ll dp[4010][2010][2],border[4010],f[2010],fac[2010];
int main(){
n=read();k=read();int i,j,re=n%k;ll tmp=0,ans=0;
fac[0]=fac[1]=1;
for(i=2;i<=n;i++) fac[i]=fac[i-1]*i%MOD;
for(i=1;i<=re;i++){//这两个循环是把链拆出来,标记哪个地方是断点
tmp+=(n/k+1);border[tmp]=1;
tmp+=(n/k+1);border[tmp]=1;
}
for(i=re+1;i<=k;i++){
tmp+=n/k;border[tmp]=1;
tmp+=n/k;border[tmp]=1;
}
dp[1][0][0]=1;
for(i=2;i<=(n<<1);i++){
for(j=0;j<=n;j++){
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1])%MOD;
if(!border[i-1]) dp[i][j][1]=dp[i-1][j-1][0];
//这里是dp方程
}
}
for(i=0;i<=n;i++) f[i]=(dp[n<<1][i][0]+dp[n<<1][i][1])%MOD;
tmp=1;
for(i=0;i<=n;i++){//容斥
ans+=tmp*f[i]*fac[n-i]%MOD;ans=(ans+MOD)%MOD;
tmp=-tmp;
}
printf("%lld\n",ans);
}

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

  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. AGC 005D.~K Perm Counting(容斥 DP 二分图)

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

  4. 【agc005d】~K Perm Counting

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

  5. [AT2062] ~K Perm Counting

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

  6. 题解-Atcoder_agc005D ~K Perm Counting

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

  7. 蓝桥杯试题 k倍区间(dp)

    问题描述 给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间. ...

  8. HDU 4352 区间的有多少个数字满足数字的每一位上的数组成的最长递增子序列为K(数位DP+LIS)

    题目:区间的有多少个数字满足数字的每一位上的数组成的最长递增子序列为K 思路:用dp[i][state][j]表示到第i位状态为state,最长上升序列的长度为k的方案数.那么只要模拟nlogn写法的 ...

  9. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

随机推荐

  1. BFS练习-POJ.2386

    Lake Counting Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 35122 Accepted: 17437 Descr ...

  2. STL 之 set的应用

    关于set Set是STL中的一个容器,特点是其中包含的元素值是唯一的,set根据其底层实现机制分为hash存储和红黑树存储两种方式,这两种结构最本质的区别就是有序和无序,红黑树的存储是有序的而has ...

  3. input属性总结

    <input type="text" readonly="readonly" /> 这个是不能输入的 readonly="readonly ...

  4. 在haoodp-2.7.3 HA的基础上安装Hbase HA

    前提安装好hadoop基于QJM的高可用 node1 HMaster node2 HMaster.HRegionServer node3 HRegionServer node4 HRegionServ ...

  5. 安装破解IDEA(个人使用)

    安装的过程,许多的教程都会有,我在这里附上一两个链接吧:https://blog.csdn.net/newabcc/article/details/80601933 他这里也有破解过程,但是比较麻烦, ...

  6. 【Effective C++ 读书笔记】条款04:确定对象使用前已先被初始化

    永远在使用对象之前先将它初始化.对于无任何成员的内置类型,你必须手工完成此事. 至于内置类型以外的任何其他东西,初始化责任落在构造函数身上.规则很简单:确保每一个构造函数都将对象的每一个成员初始化. ...

  7. ios 苹果内购订单验证 --- php实现

    验证函数: function appleVerify($receipt_data,$orderId = 0) { /* * 21000 App Store不能读取你提供的JSON对象 * 21002 ...

  8. list函数及list对象的reverse方法

    list的reverse方法,是就地reverse,不返回值 如a是一个list,a.reverse()直接将a这个list给reverse了,所以如果print(a.reverse())就是None ...

  9. C细节错误

    2018.11.20 (1)有关优先级的细节 while (c = getchar() && c == '\n') { printf("c = %d\n", c); ...

  10. [USACO1.5] 回文质数

    P1217  Prime Palindromes 题目描述 因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数. 写一个程序来找出范围[a,b](5 < ...