文章目录
上海理工大学第二届“联想杯”全国程序设计邀请赛
A.A-SOUL!
题意:
题解:
代码:
#include <bits/stdc++.h>
#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;
int const MAXN = 2e5 + 10;
int n, m, T, a[MAXN];
unordered_map<int, int> mp;
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> a[i];
sort(a + 1, a + 1 + n);
n = unique(a + 1, a + 1 + n) - a - 1;
int res = 0;
for (int i = 1; i <= n; ++i) {
mp[a[i]] = mp[a[i] - m] + 1;
res = max(res, mp[a[i]]);
}
cout << res;
return 0;
}
B.Bheith i ngra le
题意: 给定n * m的网格,对于每一个水平位置i,都有个高度hi。定义“山”为:存在l和r,使得 1 ∼ l − 1 1 \sim l-1 1∼l−1,都有 h i < = h i + 1 hi<=h_{i+1} hi<=hi+1;对于 l ∼ r l\sim r l∼r,都有 h i = h i + 1 hi=h_{i+1} hi=hi+1;对于 r + 1 ∼ n r+1\sim n r+1∼n,都有 h i > = h i + 1 hi >= h_{i+1} hi>=hi+1。问:给定n和m,求有多少种构成“山”的方案数。 1 < = n , m < = 2000 , h i > = 0 1<=n,m<=2000,hi>=0 1<=n,m<=2000,hi>=0
题解: 组合计数–隔板法。考虑枚举l和r,然后枚举这段区间内的hi。那么得到式子:
∑ i = 1 n ∑ j = i n ∑ k = 1 m C i + k − 2 k − 1 ∗ C n − j + k − 1 k − 1 \sum_{i=1}^n\sum_{j=i}^n\sum_{k=1}^m C_{i+k-2}^{k-1}*C_{n-j+k-1}^{k-1} ∑i=1n∑j=in∑k=1mCi+k−2k−1∗Cn−j+k−1k−1
解释下这个式子,对于前i-1个位置,要满足 h i < = h i + 1 h_i<=h_{i+1} hi<=hi+1。然后可以选择的高度范围为 0 ∼ k − 1 0\sim k-1 0∼k−1,那么就是在 0 ∼ k − 1 0 \sim k-1 0∼k−1 这k个数字中,选择出 i − 1 i-1 i−1 个数字的方案数。记 a i a_i ai表示选择数字i的次数,那么问题等价于求解方程 a 0 + a 1 + . . . + a k − 1 = i − 1 , a i > = 0 a_0+a_1+...+a_{k-1}=i-1,\ a_i>=0 a0+a1+...+ak−1=i−1, ai>=0 的解数目。
因为 a i > = 0 a_i>=0 ai>=0,那么按照隔板法往k-1个容器内部加入1个物品,那么就是 k − 1 + i − 1 = k + i − 2 k-1+i-1=k+i-2 k−