其他分享
首页 > 其他分享> > Codeforces Round #690 (Div. 3)解题报告

Codeforces Round #690 (Div. 3)解题报告

作者:互联网

题目链接:https://codeforces.com/contest/1462

以后要坚持补题写题解呀~

A:Favorite Sequence

题目大意

给一个序列,按照序列首尾首尾的取元素

思路

vector简单模拟

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[305];
int main(){
    int t; cin >> t;
    while(t --){
        int n; cin >> n;
        for(int i = 1; i <= n; i ++) cin >> a[i];
        vector<int> v;
        int l = 1, r = n;
        while(l < r){
            v.push_back(a[l]);
            v.push_back(a[r]);
            l ++; r --;
        } 
        if(n & 1) v.push_back(a[l]); //如果n为奇数,则会多出一个值
        for(int i = 0; i < v.size(); i ++){
            if(i) cout << " ";
            cout << v[i];
        }
        cout << endl;
    }
    return 0;
}

B:Last Year's Substring

题目大意

给一个字符串,问能否最多删除连续一段使得剩下的字符串是“2020”?

思路

因为最多删除一段,中间两边分别判断一下就好了

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
char a[305];
int main(){
    int t; scanf("%d",&t);
    while(t --){
        int n; scanf("%d%s",&n, a + 1);
        if(a[1] == '2' && a[2] == '0' && a[3] == '2' && a[4] == '0') puts("YES"); //从5开始删
        else if(a[1] == '2' & a[2] == '0' && a[3] == '2' && a[n] == '0') puts("YES"); //从4开始删
        else if(a[1] == '2' && a[2] == '0' && a[n - 1] == '2' && a[n] == '0')puts("YES");//从3开始删
        else if(a[1] == '2' && a[n - 2] == '0' && a[n - 1] == '2' && a[n] == '0') puts("YES");//从2开始删
        else if(a[n - 3] == '2' && a[n - 2] == '0' && a[n - 1] == '2' && a[n] == '0') puts("YES");//从1开始删
        else puts("NO"); 
    }
    return 0;
}

C:Unique Number

题目大意

输出最小的数位和等于x并且各个数位都不一样的值

思路

低位的数位越大越好,最后一位从9开始枚举,倒数第二位从8开始枚举,以此类推。。。减到n不够减,当n>45是,出 -1

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
int main(){
	int t; scanf("%d",&t);
	while(t --){
		int n; scanf("%d",&n);
		if(n > 45) {
			puts("-1");
			continue;
		}
		int d = 9;
		string a;
		char ch;
		while(n){
			if(n <= d){
				ch = n + '0';
				a = ch + a;
				n = 0;
			} else{
				n -= d;
				ch = d + '0';
				d --;
				a = ch + a;
			}
		}
		cout << a << endl;
	}
	return 0;
}

D:Add to Neighbour and Remove

题目大意

给出一个序列,相邻的可以左右合并,问最后最多可以分成多少段相同的值。

思路

总和是sum,枚举分成的份数(当然就是sum的因子啦),然后更新最小值

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[3005], n;
ll cal(ll x){
    ll ans = 0, res = 0;
    int i = 1;
    while(i <= n){
        res += a[i ++];
        if(res == x){
            res = 0;
            continue;
        }
        if(res > x) return n - 1; // 分不了的话只能合并成一个了
        ans ++;
    }
    return ans;
}
int main(){
    int t; scanf("%d",&t);
    while(t --){
        scanf("%d",&n);
        ll sum = 0;
        for(int i = 1; i <= n; i ++){
            scanf("%d",&a[i]);
            sum += a[i];
        }
        ll ans = n - 1;
        for(ll i = 1; i * i <= sum; i ++){
            if(sum % i == 0){ //可以分成i份和sum/i份
                ll a1 = cal(i);
                ll a2 = cal(sum / i);
                ans = min(ans, min(a1, a2));
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

E1:

题目大意

给出一个序列,抽出3个数,这3个数的最大值减去最小值小于等于2,问能抽出多少组数

思路

这是简单版本,那map存个数,分类讨论。六种情况:【a,a,a】【a,a,a+1】【a,a+1,a+1】【a,a,a+2】【a,a+2,a+2】【a,a+1,a+2】

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
map<int, int> mp;
int main(){
    int t; scanf("%d",&t);
    while(t --){
        int n; scanf("%d",&n);
        mp.clear();
        while(n --){
            int x; scanf("%d",&x);
            mp[x] ++;
        }
        ll ans = 0;
        for(auto it : mp){
            int d = it.first;
            int num = it.second;
            if(num >= 3) ans += 1ll * num * (num - 1) * (num - 2) / 6; //a,a,a
            if(mp.count(d + 1)){
                int dd = mp[d + 1];
                if(num >= 2) ans += 1ll * num * (num - 1) / 2 * dd;//a,a,a+1
                if(dd >= 2) ans += 1ll * dd * (dd - 1) / 2 * num;//a,a+1,a+1
                if(mp.count(d + 2)) {
                    ans += 1ll * num * mp[d + 1] * mp[d + 2];//a,a+1,a+2
                }
            }
            if(mp.count(d + 2)){
                int ddd = mp[d + 2];
                if(ddd >= 2) ans += 1ll * ddd * (ddd - 1) / 2 * num;//a,a+2,a+2
                if(num >= 2) ans += 1ll * num * (num - 1) / 2 * ddd;//a,a,a+2
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

E2:

题目大意

和上题一样但是m,k变成未知数,数据很大结果要取mod

思路

给的时限很多,可以双指针枚举最左边的数,然后剩下的数中取m-1个数,求个组合数

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;
ll fac[maxn], inv[maxn];
ll _pow(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
void init(){ //预处理阶乘数和阶乘数的逆元
    fac[0] = 1;
    for(int i = 1; i < maxn; i ++)
        fac[i] = fac[i - 1] * i % mod;
    inv[maxn - 1] = _pow(fac[maxn - 1], mod - 2);
    for(int i = maxn - 2; i >= 0; i --)
        inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll c(ll a, ll b){  //求组合数
    if(a < b) return 0;
    return fac[a] * inv[b] % mod * inv[a - b] % mod;
}
ll a[maxn];
int main(){
    init();
    int t; scanf("%d",&t);
    while(t --){
        int n, m, k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 1; i <= n; i ++) scanf("%d",&a[i]);
        sort(a + 1, a + n + 1);
        int l = 1; 
        ll ans = 0;
        for(int r = m; r <= n; r ++){
            while(a[r] - a[l] > k) l ++; //满足区间内跨度小于等于k
            if(r - l + 1 < m) continue;  //满足区间内数量大于等于m
            ans = (ans + c(r - l, m - 1)) % mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

F:The Treasure of The Segments

题目大意

给你n个二元组,代表线段的左右端点,问最少删几条线段,使得剩下当中存在一个线段与所有剩下的所有线段都有交集。

思路

枚举每一个二元组作为那个特殊线段时需要删的线段数,更新最小值。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
int a[maxn], b[maxn];
int x[maxn], y[maxn];
int main(){
	int t; scanf("%d",&t);
	while(t --){
		int n; scanf("%d",&n);
		for(int i = 1; i <= n; i ++){
			scanf("%d%d",&a[i], &b[i]);
			x[i] = a[i];
			y[i] = b[i];
		}
		sort(x + 1, x + n + 1);
		sort(y + 1, y + n + 1);
		int l, r, ans = n;
		for(int i = 1; i <= n; i ++){
			int l = (lower_bound(y + 1, y + n + 1, a[i]) - y) - 1; //右端点小于当前左端点的数量
			int r = n - (upper_bound(x + 1, x + n + 1, b[i]) - x) + 1;//左端点大于当前右端点的数量
			ans = min(ans, l + r); 
		}
		printf("%d\n", ans);
	}
	return 0;
}

 

标签:690,int,ll,Codeforces,num,maxn,&&,ans,Div
来源: https://blog.csdn.net/weixin_43911947/article/details/111286293