0
点赞
收藏
分享

微信扫一扫

2021年算法-笔试面试、考研题、蓝桥杯、PAT、CSP、ACM等题目汇总

cnlinkchina 2022-02-23 阅读 66

文章目录

AcWing 3485. 最大异或和 (美团2021,笔试题)

原题链接:AcWing 3485. 最大异或和 输入样例:

3 2
1 2 4

输出样例:

6

题解

为了快速算出一段区间的异或值,所以需要使用前缀和(异或),转化成求两个前缀异或的最大值。 在转换成之后,又需要保证两个前缀之间的间距不超过m,所以需要开一个cnt数组,记录当前节点是否有值,删除时需要对其-1,insert时需要+1。

代码

// https://www.acwing.com/activity/content/code/content/1261349/
#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;
const int N = 32 * 1e5 + 4;
int s[N], x;

int trie[N][2], idx;
int cnt[N]; // 删除需要的地方,当时没想到
void insert(int x, int v) {
    int p = 0;
    for (int i = 30; ~i; i--) {
        int u = x >> i & 1;
        if (!trie[p][u])
            trie[p][u] = ++idx;
        p = trie[p][u];
        cnt[p] += v;
    }
}

int query(int x) {
    int p = 0, res = 0;
    for (int i = 30; ~i; i--) {
        int u = x >> i & 1;
        if (cnt[trie[p][!u]])
            p = trie[p][!u], res = res * 2 + 1;
        else
            p = trie[p][u], res = res * 2;
    }
    return res;
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        s[i] = s[i - 1] ^ x;
    }
    insert(s[0], 1);
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (i > m)
            insert(s[i - m - 1], -1);
        res = max(res, query(s[i]));
        insert(s[i], 1);
    }
    cout << res << endl;

    return 0;
}

AcWing 3493. 最大的和(贝壳找房2021,笔试题)

原题链接:AcWing 3493. 最大的和 输入样例1:

3 1
2 5 4
0 0 1

输出样例1:

9

输入样例2:

4 3
10 5 4 7
0 1 1 0

输出样例2:

19

题解

  1. 先把所有的为1的状态求和 2. 再次遍历,如果这个状态为0,先加上这个位置的值 3. 如果此时下标i与i-m这段长度为i-(i-m)+1长度超过了m,需要去掉i-m的影响(出队) 4. 更新最大值

代码

// https://www.acwing.com/activity/content/code/content/1223424/
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N =  100000  + 5;
int arr[N];
bool st[N];
int main(){
    
    int n, m;
    long long res = 0, sum = 0;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ){
        scanf("%d", &arr[i]);
    }
    for (int i = 1; i <= n; i ++ ){
        scanf("%d", &st[i]);
        if (st[i]) sum += arr[i];
    }
    // cout << sum << endl;
    for (int i = 1; i <= n; i ++ ){
       if (!st[i]) sum += arr[i];
       if (i >= m && !st[i - m]) sum -= arr[i - m];
       res = max(res, sum);
    }
    cout << res << endl;
    return 0;
}

AcWing 3499. 序列最大收益 (中兴2021,笔试题)

原题链接:3499. 序列最大收益 输入样例:

4 1 3
1 4 2
0 3 0 1
3 0 0 0
0 0 0 0
1 0 0 0

输出样例:

3

样例解释 初始序列收益和为 w1,4+w4,2=1+0=1。
删除中间的 4 后,序列 1,2 的收益和为 w1,2=3。

题解

代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 210;

int a[N], arr[N][N], f[N][N];
int n, k, m;

int main()
{
    cin >> n >> k >> m;
    for (int i = 1; i <= m; i ++ )
        cin >> a[i];

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
            cin >> arr[i][j];
            
    // f[i][j],以i结尾,删除了k个数
    // 不同点在于前i-1个点,想要从那个点转移过来,需要删除i-u-1个点
    // f[1][0] = a[0];
    for (int i = 1; i <= m; i ++ ){
        for (int j = 0; j <= k; j ++ ){
            for(int u = i - 1; u; u--){
                if (j>=i-u-1)
                f[i][j] = max(f[i][j], f[u][j-(i-u-1)]+arr[a[u]][a[i]]);
            }
        }
    }
    
    int res = 0;
    for(int i = 0; i <= k; i++)
        res = max(res, f[m][i]);
    cout << res;
    return 0;
}

AcWing 3502. 不同路径数(贝壳找房2021,笔试题)

原题链接:AcWing 3502. 不同路径数 输入样例:

3 3 2
1 1 1
1 1 1
2 1 1

输出样例:

5

样例解释 一共有 5 种可能的 3 位数:
111 112 121 211 212

题解

(暴力枚举) O(n2) 暴力枚举,dfs 借助set判重,每次dfs将当前数位加到string的最后一位 当dfs层数达到k层时,就将数据插入到set中

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>

using namespace std;

const int N = 10;

int n, m, k;
int w[N][N];
unordered_set<int> S;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

void dfs(int x, int y, int u, int num)
{
    if (u > k) S.insert(num);
    else
    {
        for (int i = 0; i < 4; i ++ )
        {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < n && b >= 0 && b < m)
                dfs(a, b, u + 1, num * 10 + w[a][b]);
        }
    }
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            scanf("%d", &w[i][j]);

    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            dfs(i, j, 1, w[i][j]);

    printf("%d\n", S.size());
    return 0;
}

AcWing 3510. 最长公共子序列(上海交通大学考研机试题)

原题链接 AcWing 3510. 最长公共子序列

题解

因为a数组没有重复数字,所以b中的数对应a的时侯是一一对应的; 那么b数组就转换成了一系列的下标; 因为子序列是上升的; 所以公共子序列就对应了那串下标的一个子序列,该子序列是上升的; 所以最长公共子序列就转换成了最长上升子序列;

代码

// https://www.acwing.com/activity/content/code/content/1260054/
#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;
const int N = 1000005;
int a1[N], a2[N];
int f[N], len;
int main() {
    int n, a;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a), a1[a] = i;
    for (int i = 1; i <= n; i++) scanf("%d", &a), a2[i] = a1[a];
    
    for (int i = 1; i <= n; i++) {
        // printf("%d ", a2[i]);
        if (!a2[i]) continue;
        if (!len || f[len - 1] < a2[i])  f[len++] = a2[i];
        else {
            int j = lower_bound(f, f + len, a2[i]) - f;
            f[j] = a2[i];
        }
    }
    cout << len << endl;
    return 0;
}

AcWing 3489. 星期几(上海交通大学考研机试题)

原题链接 输入样例:

9 October 2001
14 October 2001

输出样例:

Tuesday
Sunday

题解

模拟题,没什么题解

代码

//https://www.acwing.com/activity/content/code/content/1260059/
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
using namespace std;
 
int month[15]= {0, 31, 28, 31, 30, 31, 30, 31 ,31,30,31,30,31};
string months[15]={"0", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
string days[10] = {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",""};
int main()
{
    int d, y;
    string M;
    int m;
    while(cin >> d >> M >> y){
        int res = d;
        for (int i = 1; i <= 14; i ++) {if (months[i] == M) {m = i; break;}}
        for (int i = 1; i < m ; i ++ ) res += month[i];
        if (y % 4 == 0 && y % 100 || y % 400 == 0) {
            if (m > 2) res++;
        }
        for (int i = 1; i < y; i ++ ){
            if (i % 4 == 0 && i % 100 || i % 400 == 0) res += 366;
            else res += 365;
        }
         cout << days[res % 7] << endl;
    }
    
    return 0;
}

AcWing 3481. 阶乘的和 (上海交通大学考研机试题)

原题链接
输入样例:

9
-1

输出样例:

YES

题解

因为数据不大,直接先计算出<1e6的阶乘,然后枚举所有的选择可能

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>

using namespace std;

int f[10];
unordered_set<int> S;

int main()
{
    for (int i = 0; i < 10; i ++ )
    {
        f[i] = 1;
        for (int j = i; j; j -- )
            f[i] *= j;
    }

    for (int i = 1; i < 1 << 10; i ++ )
    {
        int s = 0;
        for (int j = 0; j < 10; j ++ )
            if (i >> j & 1)
                s += f[j];
        S.insert(s);
    }

    int n;
    while (cin >> n, n >= 0)
        if (S.count(n))
            puts("YES");
        else
            puts("NO");
    return 0;
}

AcWing 3516. 最大面积 (今日头条2021,笔试题)

原题链接

题解

代码

// https://www.acwing.com/activity/content/code/content/1259248/

#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 3005;
bool arr[N][N];
int f[N][N];
int l[N], r[N], u[N], d[N];

int width[N];
int s[N], tt;

int calc(int h[], int n) {
    s[n + 1] = tt = 0; //边界处理

    int res = 0;
    for (int i = 1; i <= n + 1; i++) {
        int w = 0;
        while (h[i] < s[tt]) {
            w += width[tt];
            res = max(res, w * s[tt]);
            tt--;
        }
        s[++tt] = h[i], width[tt] = w + 1;
    }
    return res;
}

void init(int n, int m) {
    memset(f, 0, sizeof f);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] = (f[i - 1][j] + arr[i][j]) * arr[i][j];
        }
        u[i] = max(u[i - 1], calc(f[i], m));
    }

    memset(f, 0, sizeof f);
    for (int i = n; i; i--) {
        for (int j = 1; j <= m; j++) {
            f[i][j] = (f[i + 1][j] + arr[i][j]) * arr[i][j];
        }
        d[i] = max(d[i + 1], calc(f[i], m));
    }
    memset(f, 0, sizeof f);
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            f[i][j] = (f[i - 1][j] + arr[j][i]) * arr[j][i];
        }
        l[i] = max(l[i - 1], calc(f[i], n));
    }
    memset(f, 0, sizeof f);
    for (int i = m; i; i--) {
        for (int j = 1; j <= n; j++) {
            f[i][j] = (f[i + 1][j] + arr[j][i]) * arr[j][i];
        }
        r[i] = max(r[i + 1], calc(f[i], n));
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    getchar();
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            arr[i][j] = getchar() - '0';
            // printf("%d", arr[i][j]);
        }
        //   puts("");
        getchar();
    }
    init(n, m);
    int q, x, y;
    scanf("%d", &q);
    while (q--) {
        scanf("%d%d", &x, &y);
        x++, y++;
        printf("%d\n", max(max(l[y - 1], r[y + 1]), max(u[x - 1], d[x + 1])));
    }
    return 0;
}

AcWing 3404. 谁是你的潜在朋友 (北京大学考研机试题)

原题链接 输入样例:

4 5
2
3
2
1

输出样例:

1
BeiJu
1
BeiJu

题解

标记一个数出现多少次即可

代码

// https://www.acwing.com/activity/content/code/content/1260595/

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 210;

int n, m;
int p[N];
int s[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i ++ )
    {
        scanf("%d", &p[i]);
        s[p[i]] ++ ;
    }

    for (int i = 0; i < n; i ++ )
        if (s[p[i]] == 1) puts("BeiJu");
        else printf("%d\n", s[p[i]] - 1);
    return 0;
}

AcWing 3483. 2的幂次方 (上海交通大学考研机试题)

原题链接 输入样例:

1315

输出样例:

2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

递归

注意判断当指数为0和1时,就不继续递归下去

代码

// https://www.acwing.com/activity/content/code/content/1261347/
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

string dfs(int n)
{
    string res;
    for (int i = 14; i >= 0; i -- )
        if (n >> i & 1)
        {
            if (res.size()) res += '+';
            if (!i) res += "2(0)";
            else if (i == 1) res += "2";
            else res += "2(" + dfs(i) + ")";
        }
    return res;
}

int main()
{
    int n;
    while (cin >> n)
        cout << dfs(n) << endl;
    return 0;
}

AcWing 3333. K-优字符串 (Google Kickstart2021 Round A Problem A)

原题链接 输入样例:

2
5 1
ABCAA
4 2
ABAA

输出样例:

Case #1: 0
Case #2: 1

样例解释 对于测试数据 1,给定字符串的优良分数刚好为 1,所以不需要任何操作。
对于测试数据 2,将索引 1 处的字符改为 B 即可。

题解

把满足条件的找出来,然后减去即可

代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200010;

int n, k;
char str[N];

int main()
{
    int T;
    scanf("%d", &T);
    for (int C = 1; C <= T; C ++ )
    {
        printf("Case #%d: ", C);
        scanf("%d%d%s", &n, &k, str);
        int cnt = 0;
        for (int i = 0, j = n - 1; i < j; i ++, j -- )
            if (str[i] != str[j])
                cnt ++ ;
        printf("%d\n", abs(cnt - k));
    }

    return 0;
}

串的优良分数刚好为 1,所以不需要任何操作。
对于测试数据 2,将索引 1 处的字符改为 B 即可。

题解

把满足条件的找出来,然后减去即可

代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200010;

int n, k;
char str[N];

int main()
{
    int T;
    scanf("%d", &T);
    for (int C = 1; C <= T; C ++ )
    {
        printf("Case #%d: ", C);
        scanf("%d%d%s", &n, &k, str);
        int cnt = 0;
        for (int i = 0, j = n - 1; i < j; i ++, j -- )
            if (str[i] != str[j])
                cnt ++ ;
        printf("%d\n", abs(cnt - k));
    }

    return 0;
}
举报

相关推荐

0 条评论