AcWing 第 57 场周赛总结

T1 比大小

简单的一道签到题。

T2 数字操作

考虑分解质因数,最后的答案就是所有质因数乘起来,操作次数就是一次乘法再加上开方的次数,也有可能不乘直接开方。

乘法的作用是把每个质因数的指数变成 \(2^n\) 的形式,这样开方就可以开尽。答案就是 \(n + 1\) 或者 \(n\)。但要记得特判 \(1\) 的情况,考试的时候被卡了 \(4\) 次。

下面是 AC 的代码

#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
struct node{
    int base, expo;
};
int n, m, res = 1, step;
int prime[MAXN];
bool vis[MAXN];
vector<node> fac;
void find_prime(){
    vis[1] = true;
    for(int i = 2; i <= n; i++){
        if(!vis[i]){
            prime[++m] = i;
            for(int j = i * 2; j <= n; j += i){
                vis[j] = true;
            }
        }
    }
}
void divide(int x){
    for(int i = 1; i <= m; i++){
        int cnt = 0;
        while(x % prime[i] == 0){
            x /= prime[i];
            cnt++;
        }
        if(cnt != 0) fac.push_back((node){prime[i], cnt});
    }
}
bool check(int x){
    for(int i = 0; i < fac.size(); i++){
        if(fac[i].expo != x) return false;
    }
    return true;
}
int main(){
    scanf("%d",&n);
    if(n == 1){
        printf("1 0\n");
        exit(0);
    }
    find_prime();
    divide(n);
    for(int i = 0; i < fac.size(); i++){
        res *= fac[i].base;
    }
    int maxn = 0;
    for(int i = 0; i < fac.size(); i++){
        maxn = max(maxn, fac[i].expo);
        // printf("base = %d expo = %d\n",fac[i].base,fac[i].expo);
    }
    step = log2(maxn);
    if((1 << step) != maxn){
        step += 2;
    }else{
        if(!check(maxn)) step++;
    }
    printf("%d %d\n",res,step);
    return 0;
}

T3 最长连续子序列

开始想到用二分做,但是后面自己证明了没有单调性,所以是一个错误的算法,但是还是拿到了 \(80\%\) 的点。(但是居然被 lyw 两遍二分骗过了,可恶)

二分错误代码:

#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
typedef long long ll;
ll n, maxn;
ll a[MAXN], sum[MAXN];
bool check(ll len){
    for(ll i = 1; i + len - 1 <= n; i++){
        ll tmp = sum[i + len - 1] - sum[i - 1];
        if(tmp > 100 * len) return true;
    }
    return false;
}
void solve(){
    ll l = 1, r = n, res = 0, mid;
    while(l <= r){
        mid = (l + r) >> 1;
        if(check(mid)){
            l = mid + 1;
            res = mid;
        }else{
            r = mid - 1;
        }
    }
    printf("%lld\n",res);
}
int main(){
    // freopen("in.txt","r",stdin);
    scanf("%lld",&n);
    for(ll i = 1; i <= n; i++) scanf("%lld",&a[i]), maxn = max(maxn, a[i]);
    if(maxn <= 100){
        printf("0\n");
        exit(0);
    }
    for(ll i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];
    solve();
    return 0;
}

然后想到把每一个数字都减去 \(100\),然后求最长的区间和大于零的连续子序列,但是求长度的时候打爆了,只有 \(50\%\) 的点拿到了

错误但接近正解的代码:

#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
typedef long long ll;
ll n, sum, ans, l = 1, r;
ll a[MAXN];
int main(){
    // freopen("in.txt","r",stdin);
    scanf("%lld",&n);
    for(ll i = 1; i <= n; i++){
        scanf("%lld",&a[i]);
        a[i] -= 100;
    }
    for(int i = 1, now_l = 1; i <= n; i++){
        sum += a[i];
        if(sum < 0){
            sum=0;
            now_l = i + 1;
        }else if(sum > 0){
            r = i;
            l = now_l;
        }
    }
    printf("%d\n", r - l + 1);
    return 0;
}

最后没有打出正解,但是考完以后按照题解的思路,用单调栈打出来了

正解代码:

#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
typedef long long ll;
ll n, ans, top;
ll a[MAXN], sum[MAXN], st[MAXN];
int main(){
    // freopen("in.txt","r",stdin);
    scanf("%lld",&n);
    for(ll i = 1; i <= n; i++){
        scanf("%lld",&a[i]);
        a[i] -= 100;
    }
    for(ll i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];
    st[++top] = 0;
    for(ll i = 1; i <= n; i++){
        if(sum[st[top]] > sum[i]) st[++top] = i;
        else if(sum[st[top]] < sum[i]){
            int l = 1, r = top, mid, res;
            while(l <= r){
                mid = (l + r) >> 1;
                if(sum[st[mid]] < sum[i]){
                    r = mid - 1;
                    res = mid;
                }else{
                    l = mid + 1;
                }
            }
            ans = max(ans, i - st[res]);
        }
    }
    printf("%d\n",ans);
    return 0;
}
posted @ 2022-06-26 10:08  Night_Tide  阅读(35)  评论(0)    收藏  举报