[AGC005D] ~K Perm Counting [dp]
题面
思路
首先可以明确的一点是,本题中出现不满足条件的所有的数,都是分组的
只有模$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]的更多相关文章
- [Agc005D]K Perm Counting
[Agc005D] K Perm Counting Description 糟糕爷特别喜爱排列.他正在构造一个长度为N的排列.但是他特别讨厌正整数K.因此他认为一个排列很糟糕,当且仅当存在至少一个i( ...
- AGC 005 D - ~K Perm Counting
D - ~K Perm Counting 链接 题意: 求有多少排列对于每个位置i都满足$|ai−i|!=k$.n<=2000 分析: 容斥+dp. $answer = \sum\limits_ ...
- AGC 005D.~K Perm Counting(容斥 DP 二分图)
题目链接 \(Description\) 给定\(n,k\),求 满足对于所有\(i\),\(|a_i-i|\neq k\)的排列的个数. \(2\leq n\leq 2000,\quad 1\leq ...
- 【agc005d】~K Perm Counting
题目大意 求有多少中1~n的排列,使得\(abs(第i个位置的值-i)!=k\) 解题思路 考虑容斥,\(ans=\sum_{i=0}^{n}(-1)^ig[i](n-i)!(g[i]表示至少有i个位 ...
- [AT2062] ~K Perm Counting
AT2602 , Luogu 求对于 \(n\) 个数的排列 , 有多少种方案满足对于所有的 \(i\) , \(|P_i - i| != K\) , 答案对 \(924844033\) 取模 . \ ...
- 题解-Atcoder_agc005D ~K Perm Counting
Problem AtCoder-agc005D 题意概要:给出\(n,k\),求合法的排列个数,其中合法定义为任何数字所在位置与自身值差的绝对值不为\(k\)(即求排列\(\{A_i\}\),使得\( ...
- 蓝桥杯试题 k倍区间(dp)
问题描述 给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间. ...
- HDU 4352 区间的有多少个数字满足数字的每一位上的数组成的最长递增子序列为K(数位DP+LIS)
题目:区间的有多少个数字满足数字的每一位上的数组成的最长递增子序列为K 思路:用dp[i][state][j]表示到第i位状态为state,最长上升序列的长度为k的方案数.那么只要模拟nlogn写法的 ...
- 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. ...
随机推荐
- Delphi的Edit控件中只能输入数字且只能输入一个小数点
使用这种功能必须使用 OnKeyPress 事件,该事件是在窗体中获得键盘输入的焦点,并且在用户按键时发生.OnKeyPress 事件中有个重要参数:Key.Key 参数为Char 型,它能够获得用户 ...
- lintcode_69_二叉树的层次遍历
二叉树的层次遍历 描述 笔记 数据 评测 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 您在真实的面试中是否遇到过这个题? Yes 哪家公司问你的这个题? LinkedIn Airb ...
- 大数据学习(一) | 初识 Hadoop
作者: seriouszyx 首发地址:https://seriouszyx.top/ 代码均可在 Github 上找到(求Star) 最近想要了解一些前沿技术,不能一门心思眼中只有 web,因为我目 ...
- google云函数实现BigQuery数据操作
Google Cloud Function操作BigQuery数据库. 1.部署云函数时在配置文件中(package.json)添加一项 "@google-cloud/bigquery&qu ...
- 493. Reverse Pairs
// see more at https://www.youtube.com/watch?v=j68OXAMlTM4 // https://leetcode.com/problems/reverse- ...
- C++基础 静态成员
静态成员是类的所有 对象共有的变量,在编译 阶段就必须分配空间. 需要注意: (1)静态成员变量的定义和使用 class Test{ static int a; }; ; void main() {} ...
- [Bzoj3611]大工程(虚树+DP)
Description 题目链接 Solution 在虚树上跑DP即可 关于虚树的建立,是维护一个最右链的过程 关键代码如下: sort(A+1,A+k+1,cmp);//按dfs序排序 s[top= ...
- spark的排序方法
今天我们来介绍spark中排序的操作,spark的排序很简单,我们可以直接使用sortBy来进行,这个里面我们使用case clas,使用case class的好处是1.不用newjiukeyi 搞出 ...
- DNS域名解析服务(bind)
DNS(Domain Name System,域名系统): 用于管理和解析域名与IP地址对应关系的技术. 简单来说,就是能够接受用户输入的域名或IP地址,然后自动查找与之匹配(或者说具有映射关系)的I ...
- 十、mysql之索引原理与慢查询优化
mysql之索引原理与慢查询优化 一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还 ...