题目链接:

http://codeforces.com/contest/889/problem/C

题意:

给你 \(n\)和 \(k\)。

让你找一种全排列长度为\(n\)的 \(p\),满足存在下标 \(i\),\(p_i\)大于所有 \(p_j\),\(j\epsilon[1,i-1]\)同时大于所有\(p_i\),\(j\epsilon[i+1,i+k]\)。问你满足这样条件的排列有多少种?

题解:

设\(dp[i]\)表示以 \(i\) 结尾的,满足题目要求的\(1\) ~ \(i\)排列。

显然。

如果,\(i<=k+1\),则\(dp[i]=0\)。

因为我们考虑 \(i-1\) 在这个排列当中的位置。当 \(i-1\) 和 \(i\) 之间的数字超过 \(k\)个时,显然成立,此时共有 \((i-k-1)*(i-2)!\) 种序列。

否则,\(i-1\) 的下标\(j >= i-k\), 把排列的前 \(j\) 个数字离散化为都由\(1\) ~ \(j\) 组合之后,这些数字组成的排列一定是以 \(j\) 结尾,满足题目要求的排列,共有\(dp[j]\)个,因为后面的数字少于 \(k\)个,不可能满足题目要求。\(dp[j]\) 是离散化之后的结果,离散化之前的结果共有\(dp[j]*C(i-2,j-1)*(i-j-1)!=dp[j]*\frac{(i-2)!}{(j-1)!}\)个。可以理解为:先在剩下的 \(i-2\) 个数当中取 \(j-1\) 个排在下标为$ 1~j-1的$位置,下标 \(j\) 之后到最后一个元素之前的位置随意排列)。

所以,两种情况加起来就是:

\(dp[i]=(i-k-1)*(i-2)!+\sum_{j=i-k}^{i-1}dp[j]*\frac{(i-2)!}{(j-1)!}\)。

但是这样直接计算要 \(O(n^2)\)。

提取一下\((i-2)!\),变成:

\(dp[i]=(i-k-1)*(i-2)!+(i-2)!*\sum_{j=i-k}^{i-1}\frac{dp[j]}{(j-1)!}\)

\(= (i-2)!*[(i-k-1)+\sum_{j=i-k}^{i-1}\frac{dp[j]}{(j-1)!}]\)

后面一项 \(\frac{dp[j]}{(j-1)!}\) 就可以利用前缀和求出。阶乘的乘除可以利用逆元求出。直接算就是O(n)。

\(dp[n]\)是以 \(n\) 结尾的排列个数。我们把 \(n\) 排在不同的位置 \(h\),把\(n\)下标之前的数离散化到\(1\) ~ \(h-1\),跟上面的一样,所以最终答案为:

\(\sum_{h=1}^{n}dp[h]*\frac{(n-1)!}{(h-1)!}\)。

总复杂度:\(O(n)\)

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn = 1000010;
  5. ll inv[maxn],fac[maxn],dp[maxn],sum[maxn];
  6. const int mod =1e9+7;
  7. ll qpower(ll a,ll b){
  8. ll res = 1;
  9. while(b)
  10. {
  11. if(b&1)res = res*a%mod;
  12. b>>=1;
  13. a= a*a%mod;
  14. }
  15. return res;
  16. }
  17. int main(int argc, char const *argv[]) {
  18. ll n,k;
  19. ll ans = 0;
  20. cin>>n>>k;
  21. if(k+1>=n){
  22. printf("0\n");
  23. exit(0);
  24. }
  25. fac[0] = 1;
  26. for (int i = 1; i <=n; i++) {
  27. fac[i] = (fac[i-1] * i) %mod;
  28. }
  29. inv[n] = qpower(fac[n],mod-2);
  30. for(int i=n-1;i>=0;i--){
  31. inv[i] = inv[i+1] *(i+1);
  32. inv[i] %= mod;
  33. }
  34. memset(dp,0,sizeof(dp));
  35. memset(sum,0,sizeof(sum));
  36. for(int i=k+2;i<=n;i++){
  37. dp[i] = (i-k-1 + (sum[i-1] - sum[i-k-1] +mod)%mod)%mod;
  38. dp[i] = (dp[i] * fac[i-2]) % mod;
  39. sum[i] = sum[i-1] + (dp[i] * inv[i-1])%mod;
  40. sum[i] %= mod;
  41. ans += (((dp[i] * fac[n-1]) % mod) * inv[i-1])%mod;
  42. ans %= mod;
  43. }
  44. cout<<ans<<endl;
  45. return 0;
  46. }

ADDITION:

当然也可以把不符合题目条件的先算出来,然后用 \(n!\)减去不符合条件的个数,即为答案。

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn = 1000005;
  5. ll inv[maxn],fac[maxn],dp[maxn],sum[maxn];
  6. const int mod =1e9+7;
  7. ll qpower(ll a,ll b){
  8. ll res = 1;
  9. while(b)
  10. {
  11. if(b&1)res = res*a%mod;
  12. b>>=1;
  13. a= a*a%mod;
  14. }
  15. return res;
  16. }
  17. int main(int argc, char const *argv[]) {
  18. ll n,k;
  19. cin>>n>>k;
  20. if(k+1>=n)
  21. {
  22. printf("0\n");
  23. exit(0);
  24. }
  25. fac[0] = 1;
  26. for(int i=1;i<=n;i++){
  27. fac[i] = fac[i-1]*i%mod;
  28. }
  29. inv[n] = qpower(fac[n],mod-2);
  30. for(int i=n-1;i>=0;i--){
  31. inv[i] = inv[i+1] * (i+1) %mod;
  32. }
  33. dp[1] = sum[1] = 1;
  34. ll ans = fac[n-1];
  35. for(int i=2;i<=n;i++){
  36. dp[i] = (sum[i-1] - sum[max(0LL,i-k-1)]) *fac[i-2] %mod;
  37. sum[i] = (sum[i-1] + dp[i] * inv[i-1]) % mod;
  38. ans = (ans + dp[i] * fac[n-1] %mod * inv[i-1])%mod;
  39. }
  40. cout<<(fac[n]-ans+mod)%mod<<endl;
  41. return 0;
  42. }

Codeforces Round #445 Div. 1 C Maximum Element (dp + 组合数学)的更多相关文章

  1. Codeforces Round #174 (Div. 1) B. Cow Program(dp + 记忆化)

    题目链接:http://codeforces.com/contest/283/problem/B 思路: dp[now][flag]表示现在在位置now,flag表示是接下来要做的步骤,然后根据题意记 ...

  2. Codeforces Round #221 (Div. 1) B. Maximum Submatrix 2 dp排序

    B. Maximum Submatrix 2 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset ...

  3. Codeforces Round #276 (Div. 1) B. Maximum Value 筛倍数

    B. Maximum Value Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/484/prob ...

  4. Codeforces Round #508 (Div. 2) E. Maximum Matching(欧拉路径)

     E. Maximum Matching 题目链接:https://codeforces.com/contest/1038/problem/E 题意: 给出n个项链,每条项链左边和右边都有一种颜色(范 ...

  5. Codeforces Round #172 (Div. 2) D. Maximum Xor Secondary 单调栈应用

    http://codeforces.com/contest/281/problem/D 要求找出一个区间,使得区间内第一大的数和第二大的数异或值最大. 首先维护一个单调递减的栈,对于每个新元素a[i] ...

  6. Codeforces Round #276 (Div. 1)B. Maximum Value 筛法

    D. Maximum Value     You are given a sequence a consisting of n integers. Find the maximum possible ...

  7. Codeforces Round #599 (Div. 2) A. Maximum Square 水题

    A. Maximum Square Ujan decided to make a new wooden roof for the house. He has

  8. Codeforces Round #555 (Div. 3) F. Maximum Balanced Circle

    F. Maximum Balanced Circle 题目链接 题意 给出\(n\)个数,现在要从中选出最多的数\(b_i,b_{i+1},\cdots,b_k\),将这些数连成一个环,要求两两相邻的 ...

  9. Codeforces Round #568 (Div. 2) D. Extra Element

    链接: https://codeforces.com/contest/1185/problem/D 题意: A sequence a1,a2,-,ak is called an arithmetic ...

随机推荐

  1. MD5解密(常用语登录密码加密)

    http://pmd5.com/

  2. C++里的模板

     1.泛型编程 --即实现一个通用的标准容器库. 所谓通用的标准容器库,就是要做到:比方List类存放全部肯恩类型的对象这样的事:泛型编程让你编写一个全然一般化并可反复使用的算法,其效率与针对某特定数 ...

  3. ZOJ 3690 &amp; HDU 3658 (矩阵高速幂+公式递推)

    ZOJ 3690 题意: 有n个人和m个数和一个k,如今每一个人能够选择一个数.假设相邻的两个人选择同样的数.那么这个数要大于k 求选择方案数. 思路: 打表推了非常久的公式都没推出来什么可行解,好不 ...

  4. jquery06 jQuery.extend 给jQuery函数添加、继承 静态方法

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  5. vue的指令在webstrom下报错

    Preferences -> Editor -> Inspections找到XML,把 Unbound XML namespace prefix的勾去掉

  6. 应用Linux远程桌面(附视频)

    650) this.width=650;" border="0" alt="" src="http://img1.51cto.com/att ...

  7. CSU 1046 追杀

    Description 在一个8行9列的国际象棋棋盘上,有一名骑士在追杀对方的国王.该骑士每秒跨越一个2*3的区域,如下图所示. 而对方的国王慌忙落逃,他先沿着右下斜线方向一直跑,遇到边界以后会沿着光 ...

  8. (JavaScript基础向)日常小发现:forEach等函数的第二个参数的用法

    forEach函数用得平时用得比较多,但是从来没想到forEach函数还有第二个参数. 这里是菜鸟教程对forEach函数的详细说明:forEach的详细说明. 如上图,forEach函数有第二个参数 ...

  9. 00081_List接口

    1.List接口介绍 (1)有序的 collection(也称为序列).此接口的用户可以对列表中每个元素的插入位置进行精确地控制.用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元 ...

  10. UVALive 5292 Critical Links

    Critical Links Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Ori ...