日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Codeforces 889C Maximum Element(DP + 计数)

發布時間:2024/10/12 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces 889C Maximum Element(DP + 计数) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接??Maximum Element

題意? 現在有這一段求序列中最大值的程度片段:

(假定序列是一個1-n的排列)

int fast_max(int n, int a[]) { int ans = 0;int offset = 0;for (int i = 0; i < n; ++i)if (ans < a[i]) {ans = a[i];offset = 0;} else {offset = offset + 1;if (offset == k)return ans;}return ans; }

顯然這段程序是錯誤的……有很多可以X掉這段程序的排列

求這樣的排列有多少個。

題目是讓我們求符合這樣條件的排列個數:

1、存在某個數,他比前面的數都大并且小于$n$;

2、他比他后面$k$個數都要大。

假設“中間這個數”為$cnt$

?

假設$D(i)$為滿足$p(i) = i$的這樣的排列個數

我們可以把$D(i)$的求解分成兩個過程。

1、計算$cnt$等于$i - 1$的排列個數

2、計算$cnt$不等于$i - 1$的排列個數

?

首先如果$i <= k + 1$,則$D(i) = 0$

?

當這個序列的$cnt$為$i - 1$時,只要滿足$i - 1$和$i$之間的數大于等于$k$個即可。

于是對于$i - 1$這個數的位置的選擇,我們有$i - k - 1$種。

然后呢,除了$i - 1$和$i$這兩個數,其他數的位置隨意(因為$i$排在最后,所以排在$i - 1$前的數字都比$i - 1$要小)

所以當前這種情況對答案的貢獻為$(i - k - 1) * (i - 2)!$

?

考慮另外一種情況。

當$cnt$不等于$i - 1$的時候,一定有$cnt < i - 1$

設$i - 1$所在位置為$pos$,我們把$i - 1$之前的$pos - 1$個數離散化成一個$1$到$pos - 1$的排列

然后在這個排列的最后加上$pos$,就構成了一個$1$到$pos$并且以$pos$結尾的排列

那么如果這個排列是符合要求的,那么整個排列也是符合要求的。

于是我們枚舉$i - 1$的位置$pos$,滿足條件的位置為$i - k <= pos <= i - 1$

我們在剩下的$i - 2$個數中選出$pos - 1$個放到前$pos - 1$個位置,然后乘上$D(pos)$。

然后還要乘上$(i - pos - 1)!$,因為$i - 1$到$i$之間的數都是隨意亂放的……

于是當前這種情況對答案的貢獻為

于是我們終于推出了D(n)的公式

最后的答案怎么計算呢

我們假設$n$的位置為$pos$

那么當$p(pos) = n$的時候,前pos個數的方案數為$D(pos) * C(n - 1, pos - 1)$

后$n - pos$個數的方案數為$(n - pos)!$

所以當$p(pos) = n$的時候對答案的貢獻為$D(pos) * C(n - 1, pos - 1)*(n - pos)!$

枚舉$pos$,累加即可。

?

#include <bits/stdc++.h>using namespace std;#define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i)const int N = 1e6 + 10; const int mod = 1e9 + 7; int n, k; int f[N], s[N]; int fac[N], inv[N]; int ans = 0;inline int Pow(int a, int b, int mod){int ret(1);for (; b; b >>= 1, a = (1ll * a * a) % mod) if (b & 1) (ret = 1ll * ret * a) % mod;return ret; } void init(){fac[0] = 1;rep(i, 1, 1e6 + 1) fac[i] = 1ll * fac[i - 1] * i % mod;rep(i, 1, 1e6 + 1) inv[i] = Pow(fac[i], mod - 2, mod); }inline void up(int &a, int b) { a = (0ll + a + b) % mod;} inline void mulup(int &a, int b){ a = 1ll * a * b % mod;}int main(){scanf("%d%d", &n, &k);init();rep(i, k + 2, n){f[i] = i - k - 1;up(f[i], s[i - 1] - s[i - k - 1]);mulup(f[i], fac[i - 2]);s[i] = (0ll + s[i - 1] + 1ll * f[i] * inv[i - 1] % mod) % mod;}rep(i, 1, n) up(ans, (int)1ll * f[i] * fac[n - 1] % mod * inv[i - 1] % mod);printf("%d\n", ans);return 0; }

?

  

?

轉載于:https://www.cnblogs.com/cxhscst2/p/7935561.html

總結

以上是生活随笔為你收集整理的Codeforces 889C Maximum Element(DP + 计数)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。