本次集训随机选取了CF上的3道题,难度在1700-1800分。
899D
题目链接
http://codeforces.com/problemset/problem/899/D
题目
给定n个数,要求从中任取两个数,使得两数和的末尾的9尽量的多。在保证末尾9最多的情况下,问可以凑出多少对。(一个数可以反复使用)
题解
观察得知,当n=5时,可以凑出1个9
当n=50时,可以凑出2个9,(50+49=99)
所以我们先判断一下最多能凑出的9的个数,然后再枚举首位数字计算。
注意:当9的个数为0(n<=4)的时候,任意两个数组合都满足条件。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans, a[20], n, k = 10;
ll pow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res *= a;
a *= a;
b >>= 1;
}
return res;
}
int main() {
for (int i = 1; i <= k; i++) {
ll f = 0;
for (int j = 0; j < i; j++) f = f * 10 + 1;
a[i] = 9 * f;
}
cin >> n;
if(n<5) {cout<<n*(n-1)/2<<endl;return 0;}
ll pos = upper_bound(a + 1, a + k + 1, 2 * n - 1) - a;
pos--;
ll f = 0;
for (int i = 0; i < pos; i++) f = f * 10 + 1;
f *= 9;
for(int i=0;i<9;i++) {
ll m = i*pow(10,pos) + f;
if(m>n*2-1) break;
// cout << min(m/2,n-m/2) << endl;
ans += min(m/2,n-m/2);
}
cout << ans << endl;
return 0;
}
898D
题目链接
http://codeforces.com/problemset/problem/898/D
题目
给定n个数,每个数表示一个时间点。要求在任意连续m分钟,出现的时间点的个数<k,要问最小需要删除的时间点的个数。
题解
每次贪心的往后找,删除不满足区间的最右边的端点。
代码
#include <bits/stdc++.h>
using namespace std;
inline void read(int &x) {
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x *= f;
}
const int maxn = 200005;
int ans,n,m,k,b[maxn],a[maxn];
int main() {
read(n), read(m), read(k);
for(int i=0;i<n;i++) read(a[i]);
sort(a,a+n);
int cnt = 0;
for(int i=0;i<n;i++) {
b[++cnt] = a[i];
if(cnt>=k) {
if(b[cnt]-b[cnt-k+1]<m) {
cnt--;
ans++;
}
}
}
cout << ans << endl;
return 0;
}
888E
题目链接
http://codeforces.com/problemset/problem/888/E
题目
给定n个数(n<=35),要求从中任取若干个数,使得他们的和 mod m的值最大。
题解
对于每个数都有取和不取两种方法,那么直接暴力穷举的话状态就有 2 35 2^{35} 235种,这样必然会超时。
于是我们先枚举前n/2个,再枚举后面n/2个,存在两个集合a,b中。接着对于a中的每一个元素i,枚举b中 <m-i 的最大值,累计到结果。
由于两个<m的数加起来必然<2*m, 所以需要将两个集合中最大的元素加起来,和之前的结果比较大小,选一个最大的。
代码
#include <bits/stdc++.h>
using namespace std;
constexpr int maxn = 55;
typedef long long ll;
void read(ll &x) {
ll f=1;x=0;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x *= f;
}
ll sum,n,p,a[maxn],m,b[maxn],ans;
vector<ll> e,f;
void dfs(ll x, ll k) {
if(x>=n/2) {e.push_back(k%p);return;}
dfs(x+1,k);
dfs(x+1,k+a[x]);
}
void dfs2(ll x,ll k) {
if(x>=m) {f.push_back(k%p);return;}
dfs2(x+1,k);
dfs2(x+1,k+b[x]);
}
int main() {
read(n), read(p);
for(int i=0;i<n;i++) read(a[i]);
for(int i=n/2;i<n;i++) b[m++] = a[i];
dfs(0,0);
dfs2(0,0);
sort(e.begin(),e.end());
sort(f.begin(),f.end());
ans = (e.back()+f.back())%p;
for(auto i:e) {
ll k = lower_bound(f.begin(),f.end(),p-i) - f.begin();
if(k) k--;
ans = max(ans,(i+f[k])%p);
}
cout << ans << endl;
return 0;
}