其他分享
首页 > 其他分享> > SZUACM2022招新积分赛Day2 总结

SZUACM2022招新积分赛Day2 总结

作者:互联网

SZUACM2022招新积分赛Day2 总结

很难过但还是来补题
这次给一些题目添上了图解

题目

下午

晚上

补题

A.Gym 103438A

一种非常巧妙的转移:
从后往前扫,考虑前缀
小:出现多种前缀 f[i - 1] = n - i //长度代表可能
同:相当于一个桥,过渡过去 f[i] = f[i + 1]

#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 5;
long long f[N], ans;

int main  () {
    int n;
    cin >> n;
    string s, t;
    cin >> s >> t;
    for (int i = n - 1; i >= 0; i --) {
        if (s[i] > t[i])
            continue;
        if (s[i] < t[i])
            f[i] = n - i;
        if (s[i] == t[i])
            f[i] = f[i + 1];
        ans += f[i];
    }
    cout << ans;      
}
//大佬的666dp
//从后往前扫,考虑前缀
//小:出现多种前缀 f[i - 1] = n - i //长度代表可能
//同:相当于一个桥,过渡过去 f[i] = f[i + 1]


//同:往后找小  
//小:往后找小/同
//大:skip
//dp

//先找到第一个同一位置上s比t小的,然后
//往前:相同的可以统计进去
//往后:
//注意,一旦不符合条件就break,因为字串要连续

B. Gym 103438N

在那里模拟了半天,其实差的不多了
最后想复杂了,反而还绕路了
主题应该是当前b[i],我反过来传递成了res,所以假了

#include <bits/stdc++.h>
#define int long long 

using namespace std;
const int N = 2e5 + 5;

int n, op;
int a[N], b[N];

signed main () {
    cin >> n;
    for (int i = 0; i <= n; i ++)
        cin >> a[i];
    for (int i = 0; i <= n; i ++)
        cin >> b[i];
    
    for (int i = n; i > 0; i --) {
        int res = b[i] - a[i];
        if (res < 0)
            continue; //不用传递了
        b[i] -= res;
        res = (res + 1) / 2, b[i - 1] += res;
        op += res;
    }

    for (int i = 0; i <= n; i ++)
        if (b[i] > a[i]) {
            op = -1;
            break;
        }
        
    cout << op << endl;
}
//模拟
//每传到下一级,op+=res,res*=2
//从后往前看需求 (ci+1)/2

//n+1种尺寸:A0,A1,...An
//现有:a0个A0,a1个A1...
//至少要有:b0个A0,b1个A1...
//op:A_i->2*A_{i + 1}

//先保证前面的,再往后拆分

//eg
//1006+498+244+10

挺可惜的,逻辑还是理的不太清楚

C. CodeForces 1672A

简单博弈,总次数为偶数就后手胜

#include <bits/stdc++.h>

using namespace std;
const int N = 55;
int n;
int a[N];

void solve () {
    int op=  0;
    cin >> n;
    for (int i= 1; i <= n; i  ++)   {
        int x;
        cin >> x;
        op += x - 1;
    }

    if (op % 2 == 0)
        cout << "maomao90" << endl;
    else
        cout << "errorgorn" << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --) {
        solve ();
    }
}

实在惭愧,这是原题,然而我忘了。。。

A. 51Nod 1001

签到题,却WA了三次。。
直接i j 两头找就行了

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 50005;
int n, k;
int a[N];

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

    sort (a + 1, a + n + 1);
    bool flag = false;

    for (int i = 1, j = n; i < j; ) {
        if (a[i] + a[j] == k) {
            flag = true;
            cout << a[i] << ' ' << a[j] << endl;
            i ++, j --;
        }
        if (a[i] + a[j] < k)
            i ++;
        if (a[i] + a[j] > k)
            j --;
        
    }

    if (!flag)
        cout << "No Solution" << endl;
}
//-4 -3 -2 -1  

B.51Nod - 1105

二分

注意细节,详见代码注释

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 50005;

ll a[N], b[N];
int n, k;

int check (ll x) {
    int cnt = 0, j = n;
    for (int i = 1; i <= n; i ++) {
        while (a[i] * b[j] > x)
            j --;
        cnt += n - j; //因为最后再减了一次,所以免去那个+1
    }
    return cnt;
}

int main () {
    scanf ("%d%d", &n, &k);
    for (int i = 1; i <= n; i ++)
        scanf ("%lld%lld", &a[i], &b[i]);

    sort (a + 1, a + n + 1);
    sort (b + 1, b + n + 1);

    ll l = a[1] * b[1], r = a[n] * b[n];
    while (l < r) {
        ll mid = l + r >> 1;
        if (check (mid) < k)
            r = mid;
        else
            l = mid + 1;

    }
    printf ("%lld", r);
}
//。。。就是二分

//再优化:固定一个,枚举另一个
//若满足,则中间一整段都满足
//画个图

//若a[i]*b[j]>x,则b[j]之后所有b[i]也必定满足a[i]*b[j]
//长度为n-j+1(因为j在往回跳,所以最终为n-j)

E. Gym 102992K
构造,由重要性质\(gcd(i, i+1)=1\)可以想到整体偏移来构造。
具体如下:

得Code:

#include <bits/stdc++.h>

using namespace std;
const int N = 1e6 + 5;
int n, k;

int main () {
    cin >> n >> k;
    if (k == 0 ) {
        cout << -1;
        return 0;
    }

    int st = 2;
    for (int i = 1; i <= n; i ++) {
        if (i == k)
            cout << 1;
        else
            cout << st ++;
        if (i != n)
            cout << ' ';
    }

}
//注意一个重要性质gcd(i,i+1)=1
//所以构造方法为把1放在k位置上,
//然后以此为分界线在此之前的前移,后面的不变

//行末不能有空格!!!!!

标签:招新,const,cout,int,res,Day2,long,SZUACM2022,using
来源: https://www.cnblogs.com/CTing/p/16299603.html