动态规划专题--容斥原理--codeforces-285E Positions in Permutations
codeforces-285E \(Positions \ in \ Permutations\)
题意
给定一个序列长度为 \(n\) 的序列 , \(A=\{1 \dots n\}\)
对于 \(A\) 的排列 \(P\) , 位置 \(i\) 的值为 \(p_i\) , 定义这个点为好的满足以下条件:
\]
即 \(p_i = i + 1 \ or \ i - 1\)
问对于 \(A\) 的排列中恰好有 \(K\) 个好点的排列数。
\(k \le n \le 1000\) .
题解
定义 \(dp_{i , j , l_{(2)} , k_{(2)}}\) 为长度为 \(i\) , 有 \(j\) 个点已经被挑出作为好点的 \(\bf{取法}\) ( 或者理解为至少有 \(j\) 个好点 ) , \(l\) 表示 \(i\) 是否被选 , \(k\) 表示 \(i + 1\) 是否被选.
我们可以获得如下转移方程:
dp[i][j][0][0] = ( dp[i][j][0][0] + dp[i - 1][j][0][0] + dp[i - 1][j][1][0] ) % mod ;
dp[i][j][1][0] = ( dp[i][j][1][0] + dp[i - 1][j][0][1] + dp[i - 1][j][1][1] ) % mod ;
if ( j ) {
dp[i][j][0][0] = ( dp[i][j][0][0] + dp[i - 1][j - 1][0][0] ) % mod ;
dp[i][j][1][0] = ( dp[i][j][1][0] + dp[i - 1][j - 1][0][1] ) % mod ;
if( i != n ) {
dp[i][j][0][1] = ( dp[i][j][0][1] + dp[i - 1][j - 1][1][0] + dp[i - 1][j - 1][0][0] ) % mod ;
dp[i][j][1][1] = ( dp[i][j][1][1] + dp[i - 1][j - 1][1][1] + dp[i - 1][j - 1][0][1] ) % mod ;
}
}
解释一下:
当 \(i\) 位置不选时 , 考虑得到:
\]
\]
当 \(i\) 位置选 \(i - 1\) :
\]
\]
当 \(i\) 位置选 \(i + 1\) :
\]
\]
仔细思考易得其正确性。
设一个 \(ans_i\) 表示长度为 \(n\) , 有至少 \(i\) 个好点排列数,易得:
\]
易得最后答案为:
\]
code
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std ;
const int N = 1e3 + 10 ;
const int mod = 1e9 + 7 ;
int n , m , K ;
int dp[N][N][2][2] , ans[N] , answer ;
inline int read() {
int x = 0 , f = 1 ;
char c = getchar() ;
while ( c < '0' || c > '9' ) {
if ( c == '-' ) f = -f ;
c = getchar() ;
}
while ( c >= '0' && c <= '9' ) {
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
namespace Combination {
int D[N] ; int nueyong[N] , sum_neo[N] , sum[N] ;
inline void lear_neoyong() {
sum_neo[0] = sum_neo[1] = 1 ;
nueyong[1] = 1 ; nueyong[0] = 1 ;
sum[0] = sum[1] = 1 ;
for( int i = 2 ; i < N ; ++ i ) {
int p = mod ;
int k = p / i ;
nueyong[i] = ( k * ( p - nueyong[p % i] ) ) % p ;
sum_neo[i] = ( nueyong[i] * sum_neo[i - 1] ) % p ;
sum[i] = ( i * sum[i - 1] ) % p ;
}
}
int Quick_Pow( int alpha , int beta ) {
int ans = 1 ;
while ( beta > 0 ) {
if( beta & 1 ) ans = ( ans * alpha ) % mod ;
beta >>= 1 ; alpha = ( alpha * alpha ) % mod ;
}
return ans ;
}
int Regular_C_of_Pow_Class( int n , int m ) {
int alpha = 1 , beta = 1 , rereturn = 0 ;
if( m <= n && n >= 0 && m >= 0 ) {
for( int i = n - m + 1 ; i <= n ; ++ i ) {
alpha = ( alpha * i ) % mod ;
}
for( int i = 1 ; i <= m ; ++ i ) {
beta = ( beta * i ) % mod ;
}
rereturn = ( alpha * Quick_Pow( beta , mod - 2 ) ) % mod ;
return rereturn ;
}
else return 0 ;
}
inline int jc( int x ) {
return sum[x] ;
}
inline int neo_jc( int x ) {
if ( x == 0 ) return 1 ;
return sum_neo[x] ;
}
int Regular_C_of_Inv( int n , int m ) {
return ( ( ( jc( n ) * neo_jc( n - m ) ) % mod ) * neo_jc( m ) ) % mod ;
}
int C_Lucas_Using_Inv( int n , int m ) {
if ( m > n ) return 0 ;
if ( m == 0 ) return 1 ;
return ( Regular_C_of_Inv( n % mod , m % mod ) * C_Lucas_Using_Inv( n / mod , m / mod ) ) % mod ;
}
int C_Lucas_Using_Pow( int n , int m ) {
if( m == 0 ) return 1 ;
return ( Regular_C_of_Pow_Class( n % mod , m % mod ) * C_Lucas_Using_Pow( n / mod , m / mod ) ) % mod ;
}
void Asking_for_Derangement() {
D[0] = 1 ;
D[1] = 0 ;
D[2] = 1 ;
for( int i = 3 ; i < N ; ++ i ) {
D[i] = ( i - 1 ) * ( D[i - 1] + D[i - 2] ) % mod ;
}
}
int Regular_A( int n , int m ) {
return ( jc( n ) * neo_jc( n - m ) ) % mod ;
}
inline void Cleared() {
memset( D , 0 , sizeof(D) ) ;
memset( sum_neo , 0 , sizeof(sum_neo) ) ;
memset( sum , 0 , sizeof(sum) ) ;
memset( nueyong , 0 , sizeof(nueyong) ) ;
}
} ;
using namespace Combination ;
signed main() {
#ifndef ONLINE_JUDGE
freopen( "1.in" , "r" , stdin ) ;
freopen( "1.out", "w" ,stdout ) ;
#endif
n = read() , K = read() ;
lear_neoyong() ;
dp[1][0][0][0] = 1 ; dp[1][1][0][1] = 1 ;
for ( int i = 2 ; i <= n ; ++ i ) {
for ( int j = 0 ; j <= n ; ++ j ) {
dp[i][j][0][0] = ( dp[i][j][0][0] + dp[i - 1][j][0][0] + dp[i - 1][j][1][0] ) % mod ;
dp[i][j][1][0] = ( dp[i][j][1][0] + dp[i - 1][j][0][1] + dp[i - 1][j][1][1] ) % mod ;
if ( j ) {
dp[i][j][0][0] = ( dp[i][j][0][0] + dp[i - 1][j - 1][0][0] ) % mod ;
dp[i][j][1][0] = ( dp[i][j][1][0] + dp[i - 1][j - 1][0][1] ) % mod ;
if( i != n ) {
dp[i][j][0][1] = ( dp[i][j][0][1] + dp[i - 1][j - 1][1][0] + dp[i - 1][j - 1][0][0] ) % mod ;
dp[i][j][1][1] = ( dp[i][j][1][1] + dp[i - 1][j - 1][1][1] + dp[i - 1][j - 1][0][1] ) % mod ;
}
}
}
}
for ( int i = 0 ; i <= n ; ++ i ) {
ans[i] = ( jc( n - i ) * ( dp[n][i][0][0] + dp[n][i][1][0] ) ) % mod ;
// cout << i << ' ' << ans[i] << '\n' ;
}
int f = - 1 ;
for ( int i = K ; i <= n ; ++ i ) {
f = -f ;
answer = ( answer + ( ( ( f * ( ans[i] * C_Lucas_Using_Inv( i , K ) ) % mod ) % mod + mod ) % mod ) % mod ) % mod ;
}
cout << answer << '\n' ;
}
结尾撒花 \(\color{pink}{✿✿ヽ(°▽°)ノ✿}\)
动态规划专题--容斥原理--codeforces-285E Positions in Permutations的更多相关文章
- CodeForces - 285E: Positions in Permutations(DP+组合数+容斥)
Permutation p is an ordered set of integers p1, p2, ..., pn, consisting of n distinct positive in ...
- Codeforces 285E - Positions in Permutations(二项式反演+dp)
Codeforces 题目传送门 & 洛谷题目传送门 upd on 2021.10.20:修了个 typo( 这是一道 *2600 的 D2E,然鹅为啥我没想到呢?wtcl/dk 首先第一步我 ...
- Codeforces 285 E. Positions in Permutations
\(>Codeforces \space 285 E. Positions in Permutations<\) 题目大意 : 定义一个长度为 \(n\) 的排列中第 \(i\) 个元素是 ...
- 【CF285E】Positions in Permutations(动态规划,容斥)
[CF285E]Positions in Permutations(动态规划,容斥) 题面 CF 洛谷 题解 首先发现恰好很不好算,所以转成至少,这样子只需要确定完一部分数之后剩下随意补. 然后套一个 ...
- 【BZOJ5302】[HAOI2018]奇怪的背包(动态规划,容斥原理)
[BZOJ5302][HAOI2018]奇怪的背包(动态规划,容斥原理) 题面 BZOJ 洛谷 题解 为啥泥萌做法和我都不一样啊 一个重量为\(V_i\)的物品,可以放出所有\(gcd(V_i,P)\ ...
- 【BZOJ1042】硬币购物(动态规划,容斥原理)
[BZOJ1042]硬币购物(动态规划,容斥原理) 题面 BZOJ Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬 ...
- NOIP2018提高组金牌训练营——动态规划专题
NOIP2018提高组金牌训练营——动态规划专题 https://www.51nod.com/Live/LiveDescription.html#!#liveId=19 多重背包 二进制优化转化成01 ...
- 正睿国庆DAY2动态规划专题
正睿国庆DAY2动态规划专题 排列-例题 1~n 的排列个数,每个数要么比旁边两个大,要么比旁边两个小 \(f[i][j]\) 填了前i个数,未填的数有\(j\)个比第\(i\)个小,是波峰 \(g[ ...
- 【【henuacm2016级暑期训练】动态规划专题 I】Gargari and Permutations
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 注意这k个序列每个都是排列. 如果在每个序列中都满足y出现在x之后的话. 那么我们从x连一条有向边至y (有一个序列不满足就不连 ( ...
- Codeforces Round #337 Alphabet Permutations
E. Alphabet Permutations time limit per test: 1 second memory limit per test: 512 megabytes input: ...
随机推荐
- 在Linux驱动中使用LED子系统
在Linux驱动中使用LED子系统 原文:https://blog.csdn.net/hanp_linux/article/details/79037684 前提配置device driver下面的L ...
- Android系统启动:2-Init篇
Android系统启动:Init篇 原文:http://gityuan.com/2016/02/05/android-init/ 概述 init进程是Linux系统中用户空间的第一个进程,进程号固定为 ...
- 安卓Camera-HAL显示值与比例
安卓Camera-HAL显示值与比例 参考:https://blog.csdn.net/wang714818/article/details/78049649?utm_source=blogxgwz4 ...
- arm linux 移植 iperf3
背景 新做的硬件需要有进行一些板级接口测试:关于网络的测试很多时候只是停留在 ping 通:能够使用就算了.不知道网络的丢包率,也不知道网络吞吐的性能. 因此,需要使用一些专业化的工具来进行测试:查阅 ...
- C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏
前言 今天大姚给大家分享一款由C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏:SeeSharpSnake. 项目特点 该仓库中的项目文件和脚本可以用多种不同的配置构建相同的游戏,每个配置生成的输出大 ...
- 基于RK3588的8K视频解码显示案例分享!引领超高清工业视频时代
8K.4K.2K显示对比 2K分辨率:也称为全高清(FULL HD),它具有1920 x 1080像素的分辨率.这是目前大多数消费者电视和电脑显示器的标准分辨率,可以提供良好的图像质量. 4K分辨率: ...
- vscode 使用 python 进行 UG 二次开发 实现代码提示功能
vscode 使用 python 进行 UG 二次开发的 实现代码提示功能 用 VSCODE 进行 UG 二次开发的时候, 想要用代码提示的时候,可以用 pydev 插件, 但是,pydev 只有一个 ...
- Lambda表达式常见用法
Lambda介绍 Lambda,别名函数式编程 函数式编程是一种编程范式.它把计算当成是数学函数的求值,从而避免改变状态和使用可变数据.它是一种声明式的编程范式,通过表达式和声明而不是语句来编程. L ...
- Known框架实战演练——进销存数据结构
系统主要包含商品信息.商业伙伴(客户.供应商)信息.业务单表头信息.业务单表体信息.对账单表头信息.对账单表体信息. 1. 商品信息(JxGoods) 该表用于存储公司商品信息. 名称 代码 类型 长 ...
- 后端说,单页面SPA和前端路由是怎么回事
没有请求的路由 在传统开发中,浏览器点击一个超链接,就会像后端web服务器发送一个html文档请求,然后页面刷新.但开始单页面开发后,就完全不同了. 单页面?这个概念难以理解.我用一个js作为整个we ...