2020HAUT-暑假新生训练1 —— 题解

A题

题意: 在二维坐标系内,给你一个起点,再给你一个终点,外加一个按周期循环的干扰因素-风,问你多少天能到达终点。简单说,每天可以移动一个单位,且要风力方向移动一个单位。

题解:统计在一个周期内每天因风力移动的距离(分为两个方向)和 可以自由移动的次数,当自由移动的次数不小于风力影响后的位置到终点的距离时即可到达,要求最少天数,二分即可。

代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e6+1;
int tx[maxn], ty[maxn], n, xs, ys, xe, ye;

bool check(long long mid) {
    long long t = mid / n, f = mid % n;
    if (abs(t * tx[n] + tx[f] + xs - xe) + abs(t * ty[n] + ty[f] + ys - ye) > mid) return true;
    return false;
}

int main() {
    cin >> xs >> ys >> xe >> ye;
    cin >> n; string s; cin >> s;
    for(int i = 1; i <= n; ++ i) {
        tx[i] = tx[i-1];
        ty[i] = ty[i-1];
        if (s[i-1] == 'U') ty[i] ++;
        if (s[i-1] == 'D') ty[i] --;
        if (s[i-1] == 'L') tx[i] --;
        if (s[i-1] == 'R') tx[i] ++;
    }
    long long l = 0, r = 2e18, ans = -1;
    while(l != r) {
        long long mid = l+r >> 1;
        if (check(mid)) l = mid + 1;
        else r = mid, ans = r;
    }
    cout << ans << endl;
    return 0;
}

B题

题意:已经统计出 “00” ,“01” 或 “10”, “11” 的个数,然后根据这些统计构造出字符串。

题解:主要考虑 n0,n1,n2 为零时的情况,还有一个坑点就是 n1 的奇偶性,防止无意间多 ‘01’ (把 ‘0’ 移到最后即可)。

代码:

#include<bits/stdc++.h>

using namespace std;

int main() {
    int T; cin >> T;
    while(T --) {
        int f = 0;
        int n0, n1, n2; cin >> n0 >> n1 >> n2;
        if (n0) cout << '0';
        for(int i = 1; i <= n0; ++ i) cout << '0';
        if (n0 == 0 && n1) cout << '0'; if (n1 && n1 % 2 == 0) n1 --, f = 1;
        for(int i = 1; i <= n1; ++ i) if (i & 1) cout << '1'; else cout << '0';
        if (n1 % 2 == 0 && n2) cout << '1';
        for(int i = 1; i <= n2; ++ i) cout << '1';
        if (f == 1) cout << '0';
        cout << endl;
    }
    return 0;
}

C题

题意:给你一个字符串,找出下标为等差数列的子序的最大个数。

题解:等差数列这个限制很苛刻的,当子序长度大于2时,子序长度为m的最大个数 <= 子序长度为m-1的最大个数,但子序长度为 1 或 2 时没有任何限制,所以只用找到子序长度为 1 或 2 的最大个数即可。

代码:

#include<bits/stdc++.h>

using namespace std;

long long cnt[26][26], res[26];

int main() {
    string s; cin >> s;
    long long ans = 0;
    for(int i = 0; i < s.size(); ++ i) {
        for(int j = 0; j < 26; ++ j) {
            cnt[s[i]-'a'][j] += res[j];
            ans = max(ans, cnt[s[i]-'a'][j]);
        }
        res[s[i] - 'a' ] ++;
        ans = max(ans, res[s[i]-'a']);
    }
    cout << ans << endl;
    return 0;
}

D题

题意:给你一个长度为 n 的数组,数组中有值为 -1 的元素,把所有的该种元素用一个数值 x 替换,使得数组中相邻元素的差值最小。

题解:把所有该种元素相邻的元素存入一个数组中,排个序,x = (最大值+最小值) / 2,然后再遍历一遍数组得到最大差值即可。

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e6+1;
long long a[maxn], b[maxn];

int main() {
    int T; cin >> T;
    while(T --) {
        int n; cin >> n; int tot = 0;
        for(int i = 1; i <= n; ++ i) {
            scanf("%lld", &a[i]);
            if (a[i] == -1 && i > 1 && a[i-1] != -1) b[++tot] = a[i-1];
            if (a[i] != -1 && i > 1 && a[i-1] == -1) b[++tot] = a[i];
        }
        sort(b+1, b+tot+1);
        long long m = 0, k = 0;
        if (tot != 0) m = b[1] + b[tot] >> 1;
        for(int i = 1; i <= n; ++ i) {
            if (a[i] == -1) a[i] = m;
            if (i > 1) k = max(k, abs(a[i] - a[i-1]));
        }
        cout << k << " " << m << endl;
    }
    return 0;
}

E题

题意:给你一个01串的长度n,再给01串中1的个数,问怎么构造使得含 1 的子串最多,输出最多的个数。

题解:如果 1 都集中在一起,含 1 的子串是多了,但此时 0 也都集中在一起了,那只含 0 的子串也多了,子串总数是一定的,所以这种贪心是有问题的。我们在把 0 都分散,那只含 0 的子串最少,而子串总数是一定的,所以把 0 分散后统计出只含 0 子串的个数即可。

代码:

#include<bits/stdc++.h>

using namespace std;

int main() {
    int T; cin >> T;
    while(T --) {
        long long n, m; cin >> n >> m;
        long long sum = n*(n+1) / 2; // 子串总数
        long long t = (n-m) / (m+1), f = (n-m) % (m+1);
        cout << sum - f * (t+1) * (t+2) / 2 - (m+1-f) * t * (t+1) / 2 << endl;
    }
    return 0;
}

F题

题意:在一维坐标系上,给你 n 个区间,让你创造一个区间,若你的区间包裹了 n 个区间中的一些区间,则你的区间获得这些包裹区间的价值,且你的区间每包含一个点价值就 -k 。

题解:线段树模板题,先建一个线段树把所有区间都包裹在内,然后枚举右端点,对左端点进行前缀和处理——右端点之前的点到达右端点的花费,每次枚举都对左端点前缀和进行实时更新,且维护一个最大价值的区间。

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 2e5+1;
typedef long long LL;

struct node {
    int l, r, id; LL val, lazy;
    node(){}
    node(int l, int r, LL val, LL lazy): l(l), r(r), val(val), lazy(lazy){}
    node(int l, int id, LL val): l(l), id(id), val(val){}
    bool operator< (const node n1) {return r < n1.r;}
    node operator+ (const node n1) {return (val >= n1.val) ? node(l,r,val,0ll) : node(n1.l,n1.r,n1.val,0ll);}
}p[maxn << 2], res(1,0,0ll);
vector<node> g[maxn]; // 以i结尾的区域

void build (int root, int l, int r) {
    if (l == r) {
        p[root] = node(l, r, 0ll, 0ll);
        return ;
    }
    int mid = l+r >> 1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    p[root] = p[root<<1] + p[root<<1|1];
}

void PushDown(int root) {
    if (p[root].lazy) {
        p[root<<1].lazy += p[root].lazy;
        p[root<<1|1].lazy += p[root].lazy;
        p[root<<1].val += p[root].lazy;
        p[root<<1|1].val += p[root].lazy;
        p[root].lazy = 0;
    }
}

void updata (int root, int l, int r, int ul, int ur, int i, LL val) {
    if (l == ul && r == ur) {
        p[root].val += val;
        p[root].r = i;
        p[root].lazy += val;
        return ;
    }
    PushDown(root);
    int mid = l+r >> 1;
    if (mid >= ur) updata(root<<1,l,mid,ul,ur,i,val);
    else if (mid < ul) updata(root<<1|1,mid+1,r,ul,ur,i,val);
    else {
        updata(root<<1,l,mid,ul,mid,i,val);
        updata(root<<1|1,mid+1,r,mid+1,ur,i,val);
    }
    p[root] = p[root<<1] + p[root<<1|1];
}

int main() {
    int n, m = 0; LL k; scanf("%d%lld", &n, &k);
    for(int i = 1; i <= n; ++ i) {
        int l, r; LL val; scanf("%d%d%lld", &l, &r, &val);
        g[r].push_back(node(l, i, val));
        m = max(m, r);
    }
    build(1, 1, m);
    for(int i = 1; i <= m; ++ i) {
        updata(1, 1, m, 1, i, i, -k);
        for(auto j: g[i]) updata(1, 1, m, 1, j.l, i, j.val);
        res = res + p[1];
    }

    if (res.val == 0) {printf("0\n"); return 0;}
    vector<int> ans;
    for(int i = res.l; i <= res.r; ++ i) {
        for(auto j: g[i]) {
            if (j.l >= res.l) ans.push_back(j.id);
        }
    }
    printf("%lld %d %d %d\n", res.val, res.l, res.r, ans.size());
    for(auto i: ans) printf("%d ", i);
    return 0;
}

G题

题意: 给你一个数字t,给一个字符串s。找到满足 a-b2+c3-d4+e5 = t 的最大字典序 abcde ,且a、b、c、d、e都属于s,若无解输出 “no solution” 。(A = 1, B = 2 … Z = 26)

题解:字符串 s 按字典序从大到小排列,dfs一下即可。

代码:

在这里插入代码片#include<bits/stdc++.h>

using namespace std;
int t; string s;
int flag, a[6], b[100];

void dfs(int depth) {
    if (depth == 5) {
        if (a[0] - a[1]*a[1] + a[2]*a[2]*a[2] - a[3]*a[3]*a[3]*a[3] + a[4]*a[4]*a[4]*a[4]*a[4] == t) {
            for(int i = 0; i < 5; ++ i) cout << char(a[i] - 1 + 'A'); cout << endl;
            flag = 1;
        }
        return ;
    }
    for(int i = s.size() - 1; i >= 0; -- i) {
        if (b[i]) continue;
        a[depth] = s[i] - 'A' + 1;
        b[i] = 1;
        dfs(depth+1);
        b[i] = 0;
        if (flag) return ;
    }
}

int main() {
    string ss = "END";
    while(cin >> t >> s) { flag = 0;
        if (t == 0 && s == ss) break;
        for(int i = 0; i < s.size(); ++ i) b[i] = 0;
        sort(s.begin(), s.end());
        dfs(0);
        if (flag == 0) cout << "no solution" << endl;
    }
    return 0;
}

在使用Matlab中求平均值的方法有多种。其中一种方法是通过使用mean函数来计算平均值。例如,如果你有一个向量或矩阵x,你可以使用mean(x)来计算它的平均值。另外,如果你想计算矩阵的每一列的平均值,你可以使用mean(x, 1),如果你想计算每一行的平均值,你可以使用mean(x, 2)。 另外,如果你想计算一个魔方矩阵的平均值,你可以使用magic函数生成魔方矩阵,然后再使用mean函数来计算它的平均值。例如,如果你想计算一个3x3的魔方矩阵的平均值,你可以使用mean(magic(3))。 此外,在Matlab中还有其他一些函数可以用来计算平均值,比如median函数用于计算中位数、mode函数用于计算众数等等。你可以根据具体的需求选择使用适当的函数来计算平均值。 综上所述,你可以使用mean函数来计算Matlab中的平均值,也可以根据具体情况使用其他函数来计算平均值。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [MATLAB常用函数汇总](https://blog.csdn.net/haut_ykc/article/details/106444673)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值