codeforces Round #632 (Div. 2)C. D.F题解

Codeforces Round 632 (Div. 2)C. D.F题解

比赛链接

C - Eugene and an array

题意:

求一个array的有多少subarray是good的,subarray定义为子串,必须怜恤。一个array是good的条件是其全部subarray的和不为0。

题解:

求一个前缀和,使用map保存每一个前缀和的下标,一旦出现相同的前缀和,就是出现和为0的串,所以全部串都不应该包括它。

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <map>
using namespace std;
const  int N=2e5+10;
#define ll long long
int a[N];
map<ll,int>pos;
int main() {
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    ll sum =0;
    int p=-1;
    ll ans = 0;
    pos[0]=0; //important
    for(int i=1;i<=n;i++) {
        sum += a[i];
        if (pos.count(sum))p = max(p, pos[sum]);
        ans += i - (p + 1);
        pos[sum] = i;
    }
    printf("%lld
",ans);
    return 0;
}

D - Challenges in school №41

题意:

变形的等价问题为,输入0,1串,每次可以交换任意组(最少一组)的连续的两个0,1的位置,最后使得全部1在左边,全部0在右边。求构造一个恰好交换k次的方案。输出每次交换的每组中1的位置

题解:

有点类似冒泡排序,把1全部冒到左边即可。
最小的min_k:每次交换全部的全部相邻的0,1对。
最大的max_k:每次交换一组0,1队。
输入的k必须位于二者之间。
用最小的min_k转换到任意一个满足条件的k(代码细节学dls写的。

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
const int  N=3005;
char arr[N];
int main() {
    int n,k;
    scanf("%d%d",&n,&k);
    scanf("%s",arr);
    vector<vector<int> > ps = vector<vector<int>>(k,vector<int>());
    int tol = 0;
    int m=0;
    while (1) {
        vector<int> step;
        for (int i = 0; i < n - 1; i++) {
            if (arr[i] == 'R' && arr[i + 1] == 'L')step.push_back(i), tol++;
        }
            if (step.empty())break;
            if (m >= k) {
                puts("-1");
                return 0;
            }
            ps[m++] = step;
            for (auto x:step)swap(arr[x], arr[x + 1]);
        }
        if(k>tol){
            puts("-1");
            return 0;
        }
        int fs = m-1;//最少的
        for(int i=k-1;i>=0;i--){
            if(ps[fs].empty())fs--;
            if(!ps[i].empty())break;
            ps[i] = vector<int>{ps[fs].back()};
            ps[fs].pop_back();
        }
        for(int i=0;i<k;i++){
            printf("%d ",ps[i].size());
            for(auto x:ps[i])printf("%d ",x+1);
            puts("");
        }
 
    return 0;
}

F. Kate and imperfection

题意:

在1~n的n个数中,对于k∈[2,n],在n个数中取k个数,选出k的数,使得他们最大gcd最小。

题解:

素数筛类似。
因为求的是最大gcd的最小,所以我们先尽可能的拿素数,素数拿完以后,再拿一个数,必然有一对不互质,所以我们要尽量使答案变小,即因子小的先拿,最后就可以得到从小到大输出的结论。
这样逻辑似乎还是有点问题,依然不能证明这就是最优方案。

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <map>
#include <algorithm>
#include <math.h>
using namespace std;
const  int N=5e5+10;
#define ll long long
int a[N];
int pr[N];
map<ll,int>pos;
void solve(int n){
    for(int i=1;i<=n;i++)pr[i]=1;
    for(int i=2;i<=n;i++){
        for(int j=2*i;j<=n;j+=i){
            pr[j] = i;//目前的最大因子
        }
    }
}
int main() {
    int n;
    scanf("%d",&n);
    solve(n);
    sort(pr+1,pr+n+1);
    for(int i=2;i<=n;i++){
        printf("%d ",pr[i]);
    }
 
 
    return 0;
}
原文地址:https://www.cnblogs.com/gzr2018/p/12680008.html