Codeforces Round #175 DIV2 E Positions in Permutations
来源:互联网 发布:都市天际线优化mod 编辑:程序博客网 时间:2024/05/22 02:03
题目链接
题意:对于某个排列p1,p2,...pn,位置i为good position当且仅当| pi - i | = 1,给你一个N,表示排列的元素个数,求满足恰好有K个good position的排列的个数,对结果Mod 1000000007。
思路:DP。首先很容易就可以想到如下的状态dp,用dp[i][j] 表示前i个位置中正好有j个位置是good position的种数。那么对于第i个位置,它就可以分成两大种情况:
a、第i个位置不是good ; 这时候我们可以很容易地实现状态转移:dp[i][j] = dp[i-1][j] 。
b、第i个位置是good。 这种情况又可以分成两种小情况:
b1.i的取值(即pi的值)是i-1; 但是这里有会带来另外一个问题,那就是i-1是否可用的问题,换句话说就是i-2位置是否已经将i-1这个数已经用掉了,所以我们可以再加入一维状态s来表示i的最后三位的状态。
b2.i的取值是i+1 ,此时可以不受前面限制地进行转移。
最后我们可以由dp求出整个排列中只有i个元素是good的值,记为sum[i],sum[i] *= fac[N-i],那么sum[i]就是至少有i个元素是good的总数,这里还特别需要注意的一点就是sum[i] = a[i] + C[i+1][i]*a[i+1] + C[i+2][i]*a[i+2]....,所以我们最后可以反解出a[K]。
代码:
#include <stdio.h>#include <string.h>typedef long long LL ;const int NN = 1010 ;const LL Mod = 1000000007 ;LL N , K ;LL dp[NN][NN][2][2][2] ;LL sum[NN] ;LL fac[NN] ;LL a[ NN ] ;LL C[NN][NN] ;void DP(){ memset( dp, 0 ,sizeof(dp) ) ; dp[1][0][0][0][0] = 1 ; if( N > 1 ) dp[1][1][0][0][1] = 1 ; for(int i=1;i<N;i++){ for(int j=0;j<=i;j++){ for(int a=0;a<2;a++){ for(int b=0;b<2;b++){ for(int c=0;c<2;c++){ if( dp[i][j][a][b][c] == 0 ) continue ; int tmp = dp[i][j][a][b][c] ; dp[i+1][j][b][c][0] = ( dp[i+1][j][b][c][0] + tmp ) % Mod ; if( b == 0 ) dp[i+1][j+1][b][c][0] = ( dp[i+1][j+1][b][c][0] + tmp ) % Mod ; if( i+2<=N ) dp[i+1][j+1][b][c][1] = ( dp[i+1][j+1][b][c][1] + tmp ) % Mod ; } } } } } for(int i=0;i<=N;i++){ sum[i] = 0 ; sum[i] = dp[N][i][0][0][0] + dp[N][i][0][0][1] + dp[N][i][0][1][0] + dp[N][i][0][1][1] + dp[N][i][1][0][0] + dp[N][i][1][0][1] + dp[N][i][1][1][0] + dp[N][i][1][1][1] ; sum[i] %= Mod ; sum[i] = sum[i] * fac[N-i] % Mod ; }}int main(){ fac[1] = fac[0] = 1 ; for(LL i=2;i<=1000;i++) fac[i] = fac[i-1] * i % Mod ; C[0][0] = C[1][0] = C[1][1] = 1 ; for(int i=2;i<=1000;i++){ for(int j=0;j<=i;j++){ C[i][j] = C[i-1][j-1] ; if( i-1>=j ) C[i][j] = (C[i][j] + C[i-1][j]) % Mod ; } } while( scanf("%d %d",&N,&K) == 2 ){ DP() ; a[N] = sum[N] ; for(int i=N-1;i>=K;i--){ LL tmp = sum[i] ; for(int j=i+1;j<=N;j++){ LL mid = C[j][i] * a[j] ; mid %= Mod ; tmp -= mid ; if( tmp < 0 ) tmp += Mod ; } a[i] = tmp ; } printf("%d\n",(int)a[K] ); } return 0 ;}
- Codeforces Round #175 DIV2 E Positions in Permutations
- Codeforces Round #175 (Div. 2) E Positions in Permutations
- Codeforces 285E - Positions in Permutations 【题解待补全】
- Codeforces 285E Positions in Permutations (dp + 容斥)
- codeforces 285E Positions in Permutations(DP+容斥,hard)
- codeforces 285E. Positions in Permutations (容斥原理+DP)
- Codeforces Round#99 E(Div2)
- codeforces div2 round#230 E
- codeforces Round 377 Div2 E
- codeforces Round #237(div2) E解题报告
- codeforces Round #241(div2) E解题报告
- codeforces Round #264(div2) E解题报告
- codeforces Round #263(div2) E解题报告
- codeforces Round #274(div2) E解题报告
- codeforces Round #261(div2) E解题报告
- codeforces Round #260(div2) E解题报告
- codeforces Round #259(div2) E解题报告
- Codeforces Round #402 (Div2)E题
- 您年轻时的创意和梦想还在吗?
- 对字节码文件的抑或加密
- ibatis解决sql注入问题
- 绘图(VC_Win32)
- 三角形类
- Codeforces Round #175 DIV2 E Positions in Permutations
- PC不会死,它只会逐渐凋零…
- LLVM pass manager debugging
- Linux errno调试方法
- Chapter 12 线程控制
- 毁三观
- PC如果死亡, 智能手机与云计算可否一统天下
- 试用Office 365 家庭高级版的十大理由
- libevent跨平台事件驱动库简介