[AGC005D]~K Perm Counting-二分图-动态规划
来源:互联网 发布:淘宝客服链接 编辑:程序博客网 时间:2024/06/06 08:24
~K Perm Counting
Problem Statement
Snuke loves permutations. He is making a permutation of length N.
Since he hates the integer K, his permutation will satisfy the following:
Let the permutation be a1,a2,…,aN. For each i=1,2,…,N, |ai−i|≠K.
Among the N! permutations of length N, how many satisfies this condition?
Since the answer may be extremely large, find the answer modulo 924844033(prime).
Constraints
2≦N≦2000
1≦K≦N−1
Input
The input is given from Standard Input in the following format:
N K
Output
Print the answer modulo 924844033.
Sample Input 1
3 1
Sample Output 1
2
2 permutations (1,2,3), (3,2,1) satisfy the condition.
Sample Input 2
4 1
Sample Output 2
5
5 permutations (1,2,3,4), (1,4,3,2), (3,2,1,4), (3,4,1,2), (4,2,3,1) satisfy the condition.
神题一道……
这无比风骚的操作真是令人震惊和赞叹啊。
题意:
求所有满足条件的1到n的排列
思路:
考虑把值和位置之间的关系建成一个二分图。
假定左半的N个点依次代表值1~N,右半的N个点依次代表位置1~N。
那么,一条边
可以发现所有不合法的情况均包含形如
令
考虑剩下的位置未知,那么采用容斥,最终结果为:
那么剩下的就是如何计算
考虑建出只含所有不合法边的方案数
可以发现这个二分图将会是如下的样子(k=3):(想象相同编号的位置之间存在一条边)
1 42 53 64 15 26 31 42 53 6
这样的极其有规律的折线便是能找到的所有匹配。
考虑把所有这样的链以任意顺序串起来,一起dp:
令
那么可以得到转移方程:
然而考虑到咱现在是把所有链串在一起DP,链与链相交的地方是没有边的。
那么按照把所有连串起来的顺序,记录每个链的结尾,在结尾处强制跳过1的状态的转移即可。
最后
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;const int N=4009;const int md=924844033;int n,k;bool vis[N][N];int ed[N],tot;int f[N][N][2];int g[N],fac[N];int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) for(int j=0;j<=1;j++) if(!vis[i][j]) { int len=0; for(int x=i,y=j;x<=n;x+=k,y^=1) vis[x][y]=1,++len; ed[tot+=len]=1; } f[1][0][0]=1; for(int i=1;i<=tot;i++) for(int j=0;j<=n;j++) { f[i+1][j][0]=(f[i][j][0]+f[i][j][1])%md; if(!ed[i]) f[i+1][j+1][1]=f[i][j][0]; } for(int i=0;i<=n;i++) g[i]=(f[tot][i][0]+f[tot][i][1])%md; fac[0]=1; for(int i=1;i<=n;i++) fac[i]=(ll)fac[i-1]*i%md; int ans=fac[n]; for(int i=1,j=-1;i<=n;i++,j=-j) ans=((ll)ans+md+(ll)j*fac[n-i]*g[i]%md)%md; printf("%lld\n",ans); return 0;}
- [AGC005D]~K Perm Counting-二分图-动态规划
- [agc005d]~K Perm Counting
- [AtCoder AGC005 D][容斥][DP] ~K Perm Counting
- [BZOJ 1072] SCOI 2007 排列perm · 动态规划
- BZOJ_P1072 [SCOI2007]排列perm(状态压缩动态规划)
- Bzoj2111:[ZJOI2010]Perm 排列计数:树形动态规划+组合数学
- 动态规划 problem K
- 动态规划K
- Counting the String 动态规划 + KMP
- leetcode -- 338. Counting Bits 【动态规划】
- POJ 3046 -- Ant Counting (动态规划)
- 338. Counting Bits(动态规划)
- 动态规划解338. Counting Bits
- k好数(动态规划)
- 动态规划—Problem K
- “k车问题”&动态规划
- POJ 3046 Ant Counting(“动态规划” 优化递推关系式)
- 挑战练习题2.3动态规划 poj3046 Ant Counting dp
- Redis学习07——存储有序字符串集合(sorted set)
- 数据库连接池
- 工作心路历程系列2:离职大公司入职创业公司心路历程
- NodeJs随手记
- 64. Minimum Path Sum(Java)
- [AGC005D]~K Perm Counting-二分图-动态规划
- ES6——Descrotor(修饰器)
- 继承与多态
- Linux 基本操作(二)————Linux系统结构、文件管理、通配符
- 简单理解mysql主从复制
- 基于Dubbo的分布式系统架构(五):在Linux操作系统上手工部署Dubbo服务
- 关于ubuntu英文版的字体问题
- 线程池的简介和使用
- spring IOC源码分析(1)