8.8集訓
阿新 • • 發佈:2020-08-08
上午
考試
下午
講圖論,改題
第一題
給定一個長度為\(n\)的序列,求這個序列所有長度為\(k\)的子序列的最大值之和,答案對\(1e9+7\)取模
顯然,觀察題面發現是“子序列”,也就是可以不連續
所以我們首先排序,然後考慮\(a[i]\)對於答案造成的貢獻,發現以\(a[i]\)為最大值的序列,\(i-1\)之前的東東他都可以造成貢獻,變相的說,是在前\(i-1\)個數裡面,選\(k-1\)個,然後這麼多次方案,\(a[i]\)對於每個方案都有貢獻,
於是答案呼之欲出啊:\(Ans = \sum_\limits {i = k} ^nC_{i-1}^{k-1}\times a[i]\),可惜在考場上沒想出來,一直在想資料結構單調棧之類的去維護他,最後沒辦法,打了二十分暴力走人
#include <bits/stdc++.h> #define LL long long #define debug using namespace std; const int N = 1e5+66, mod = 1e9+7; int n, k; int a[N]; LL c[N][66], res; inline int thestars() { cin >> n >> k; for (int i = 1; i <= n; ++ i) scanf ("%d", &a[i]); sort (a + 1, a + n + 1); for (int i = 0; i <= n; ++ i) c[i][0] = 1; for (int i = 1; i <= n; ++ i) { for (int j = 1; j < k; ++ j) { c[i][j] = (c[i - 1][j] + c[i - 1][j - 1])%mod; } } for (int i = k; i <= n; ++ i) res = (res + c[i - 1][k - 1]*a[i])%mod; cout << res; return 0; } int youngore = thestars(); signed main() {;}
第二題
題目大意:在一個有\(n\)個站點的路上,對於\(1\leq i < n\),站點\(i\)可以一票到達站點\(i+1,i+2, i+3......Min(i+a_i, n)\)
求任意兩點\(i,j\)從\(i\text~j\)的最少票數和,即求\(\sum_\limits{i=1}^{n-1}\sum_\limits{j=i}^{n} p(i,j)\)其中\(p(i,j)\)表示\(i\text~j\)的最少票數
狀態:設\(f[i]\)表示\(\sum_\limits{j = i+1}^np(i,j)\),即\(i\text~j\)的最少票數和,
轉移:
- 對於\((i,i+a_i\rbrack\)
- 對於\((i+a_i,n\rbrack\),選擇一個合適的\(j\)作為跳板,跳到終點,顯然選擇一個\({j+a[j]}_{max}\)是最合適不過的了
- 故當\(i+a_i=n\)時,\(f[i] = n-i\),表示\(i+1 \text~n\)都可以一票走
- 而當\(i+a_i<n\)時,用樹狀陣列或線段樹查詢\((i,i+a_i \rbrack\)中,\(j+a_i\)最大的\(j\)
- 轉移呼之欲出:\(f[i] = a_i+f[j]-(a_i -j)+(n-a_i)\)
結果:\(Ans = \sum_\limits{i=1}^{n-1}f[i]\)
給出AC程式碼:
#include <bits/stdc++.h>
#define lowbit(x) (x&-x)
#define LL long long
#define debug
using namespace std;
const int N = 1e5+66;
int n, a[N], mp[N], t;
LL f[N], res;
inline void chenge(int x) {
for (int i = x; i <= n; i += lowbit(i)) {
if (a[mp[i]] < a[x]) {
mp[i] = x;
}
}
}
inline int ask(int x) {
int yhm(0);
for (int i = x; i; i -= lowbit(i)) {
if (a[yhm] < a[mp[i]]) {
yhm = mp[i];
}
}
return yhm;
}
inline int thestars() {
scanf ("%d", &n);
for (int i = 1; i <= n-1; ++ i) {
scanf ("%d", &a[i]);
a[i] = min (a[i]+i, n);
}
for (int i = n-1; i; -- i) {
f[i] = a[i] - i;
if (a[i] < n) t = ask(a[i]), f[i] += f[t] - (a[i] - t) + (n - a[i]);
chenge(i);
}
for (int i = 1; i <= n; ++ i) res += f[i];
cout << res;
return 0;
}
int youngore = thestars();
signed main() {;}