杂题小记(2023.02.28)

杂题小记(2023.02.28)

更好的阅读体验戳此进入

SP2713 GSS4 - Can you answer these queries IV

题面

给定序列,区间开方,区间求和。

Solution

考虑对于 $ 10^{18} $ 的数最多开方 $ 6 $ 次就会变为 $ 1 $,则额外维护一个标记表示是否区间均为 $ 0 $ 或 $ 1 $,遇到标记则不继续修改,可以证明复杂度是对数级的。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;



template < typename T = int >
inline T read(void);

int N, M;
ll A[110000];

class SegTree{
private:
    ll sum[110000 << 2];
    bool flag[110000 << 2];
    #define LS (p << 1)
    #define RS (LS | 1)
    #define MID ((gl + gr) >> 1)
public:
    void Clear(int p = 1, int gl = 1, int gr = N){
        sum[p] = flag[p] = 0;
        if(gl == gr)return;
        Clear(LS, gl, MID), Clear(RS, MID + 1, gr);
    }
    void Pushup(int p){
        sum[p] = sum[LS] + sum[RS];
        flag[p] = flag[LS] & flag[RS];
    }
    void Build(int p = 1, int gl = 1, int gr = N){
        if(gl == gr)return sum[p] = A[gl = gr], flag[p] = sum[p] == 0 || sum[p] == 1, void();
        Build(LS, gl, MID), Build(RS, MID + 1, gr);
        Pushup(p);
    }
    void Modify(int l, int r, int p = 1, int gl = 1, int gr = N){
        if(gl == gr)return sum[p] = (int)sqrt(sum[p]), flag[p] = sum[p] == 0 || sum[p] == 1, void();
        if(flag[p])return;
        if(l <= MID)Modify(l, r, LS, gl, MID);
        if(r >= MID + 1)Modify(l, r, RS, MID + 1, gr);
        Pushup(p);
    }
    ll Query(int l, int r, int p = 1, int gl = 1, int gr = N){
        if(l <= gl && gr <= r)return sum[p];
        if(l > gr || r < gl)return 0;
        return Query(l, r, LS, gl, MID) + Query(l, r, RS, MID + 1, gr);
    }
}st;

int main(){
    int cnt(0);
    while(true){
        N = read();
        // if(!~N)exit(0);
        printf("Case #%d:\n", ++cnt);
        for(int i = 1; i <= N; ++i)A[i] = read < ll >();
        st.Build();
        M = read();
        while(M--){
            int opt = read();
            if(opt == 0){
                int l = read(), r = read();
                st.Modify(min(l, r), max(l, r));
            }else{
                int l = read(), r = read();
                printf("%lld\n", st.Query(min(l, r), max(l, r)));
            }
        }printf("\n");
        st.Clear();
    }
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    if(c == EOF)exit(0);
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

LG-P4391 [BOI2009]Radio Transmission 无线传输

题面

给定字符串,其是由一个字符串多次重复得到的(是一个串无限重复后串的任意子串),求该字符串的最短长度。

Solution

只能说这题确实高妙!感觉推导过程和 border 的那一套理论差不多。

首先结论就是用 KMP 求出 $ nxt $ 后 $ n - nxt_n $ 即为答案。

按照类似 border 某些前置知识的证明思路证明即可,也就是考虑对于减去最长前后缀后剩下的一段,会对应着前缀末尾段,然后再对应到后缀对应段,一直对应下去,发现一定合法。

对于其一定为最优的证明,可以考虑若存在一个更小的循环节,多次循环之后最后会剩一个残块,不考虑这个残块及其影响后一定会形成一个更长前后缀,得证(这东西适合画图李姐一下,口糊肯定很抽象)。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define S(i) (S.at(i - 1))

template < typename T = int >
inline T read(void);

int N;
string S;
int nxt[1100000];

int main(){
    N = read();
    cin >> S;
    int lst(0);
    for(int i = 2; i <= N; ++i){
        while(lst && S(lst + 1) != S(i))lst = nxt[lst];
        if(S(lst + 1) == S(i))++lst;
        nxt[i] = lst;
    }printf("%d\n", N - nxt[N]);

    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

LG-P2375 [NOI2014] 动物园

题面

给定字符串 $ S $,求 $ S $ 的每个前缀子串的相同且不重叠前后缀的数量。

Solution

想麻烦了,找了半天性质,实际上很简单。

首先不考虑重叠,对于一般的求数量我们只需要在求 $ nxt $ 的时候同时转移一下 $ num $ 即可,然后考虑重叠,不难想到重新跑一遍 KMP,对于每次求出来的 $ nxt_i $ 一直跳到 $ nxt_i \le \lfloor \dfrac{i}{2} \rfloor $,然后取 $ num_{nxt_i} $ 即为答案。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define MOD (ll)(1e9 + 7)
#define S(i) (S.at(i - 1))

template < typename T = int >
inline T read(void);

string S;
int nxt[1100000];
int num[1100000];

int main(){
    int T = read();
    while(T--){
        ll ans(1);
        cin >> S;
        int N = S.length();
        int lst(0);
        nxt[0] = nxt[1] = num[0] = 0, num[1] = 1;
        for(int i = 2; i <= N; ++i){
            while(lst && S(lst + 1) != S(i))lst = nxt[lst];
            if(S(lst + 1) == S(i))++lst;
            nxt[i] = lst, num[i] = num[lst] + 1;
        }lst = 0;
        for(int i = 2; i <= N; ++i){
            while(lst && S(lst + 1) != S(i))lst = nxt[lst];
            if(S(lst + 1) == S(i))++lst;
            while(lst > (i >> 1))lst = nxt[lst];
            (ans *= (num[lst] + 1)) %= MOD;
        }
        // int same(1);
        // while(same + 1 <= N && S(same + 1) == S(same))++same;
        // ll ans(1);
        // for(int i = 1; i <= N; ++i)(ans *= nxt[i] ? (S(1) == S(i) ? min(nxt[i] + 1, same + 1) : 2) : 1) %= MOD;
        printf("%lld\n", ans);
    }
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

LG-P3193 [HNOI2008]GT考试

题面

求长度为 $ n $ 的序列中不存在长度为 $ m $ 的子串的方案数。

Solution

首先按照一般思路考虑一个朴素 DP,即令 $ dp(i, j) $ 表示匹配了文本串的前 $ i $ 位与模式串的前 $ j $ 位的方案数,发现并不好进行转移,可能性太多,于是想到可以预处理出 $ g(i, j) $ 表示对于模式串,从匹配了前 $ i $ 转移到匹配了前 $ j $ 的方案数,则转移显然:

\[dp(i, j) = \sum_{k = j - 1}^m dp(i - 1, k) \times g(k, j) \]

显然可以等效写成:

\[dp(i, j) = \sum_{k = 0}^{m - 1} dp(i - 1, k) \times g(k, j) \]

发现其满足矩阵形式,且 $ g $ 为定值,可以通过矩阵快速幂优化。

对于 $ g $ 的预处理,考虑 KMP,先朴素跑一遍 KMP,然后枚举每一位,钦定当前的最长前后缀为目前的整个前缀,这是显然的,然后按照一般的 KMP 的匹配思路往前跳到合法能匹配的最长,如此大概统计一下复杂度卡满应该是 $ O(m^2v) $ 的,其中 $ v = 10 $ 为值域。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define S(i) (S.at(i - 1))
#define MOD (K)

template < typename T = int >
inline T read(void);

int N, M, K;
string S;
int nxt[30];
int G[30][30];

class Matrix{
private:
public:
    int v[20][20];
    Matrix(void){memset(v, 0, sizeof v);}
    friend Matrix operator * (const Matrix &a, const Matrix &b){
        Matrix ret;
        for(int i = 0; i < M; ++i)
            for(int j = 0; j < M; ++j)
                for(int k = 0; k < M; ++k)
                    (ret.v[i][j] += a.v[i][k] * b.v[k][j] % MOD) %= MOD;
        return ret;
    }
    void Print(void){
        printf("Matrix:\n");
        for(int i = 0; i < M; ++i)
            for(int j = 0; j < M; ++j)
                printf("%d%c", v[i][j], j == M - 1 ? '\n' : ' ');
    }
}base, ans;

Matrix qpow(Matrix a, ll b){
    Matrix ret, mul(a);
    for(int i = 0; i < M; ++i)ret.v[i][i] = 1;
    while(b){
        if(b & 1)ret = ret * mul;
        b >>= 1;
        mul = mul * mul;
    }return ret;
}

int main(){
    N = read(), M = read(), K = read();
    cin >> S;
    int lst(0);
    for(int i = 2; i <= M; ++i){
        while(lst && S(lst + 1) != S(i))lst = nxt[lst];
        if(S(lst + 1) == S(i))++lst;
        nxt[i] = lst;
    }
    for(int i = 0; i < M; ++i)
        for(int j = '0'; j <= '9'; ++j){
            int lst = i;
            while(lst && S(lst + 1) != j)lst = nxt[lst];
            if(S(lst + 1) == j)++lst;
            ++G[i][lst];
        }
    for(int i = 0; i < M; ++i)
        for(int j = 0; j < M; ++j)
            base.v[i][j] = G[i][j] % MOD;
    ans.v[0][0] = 1;
    ans = ans * qpow(base, N);
    int rans(0);
    for(int i = 0; i < M; ++i)(rans += ans.v[0][i]) %= MOD;
    printf("%d\n", rans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

LG-P4180 [BJWC2010] 严格次小生成树

题面

求连通图的严格次小生成树。

Solution

存在如下方法,正确性可感性理解,理性证明未知。

考虑任意建出一棵 MST,然后枚举所有没有在 MST 中的边,分别找出每条边的 $ s, t $ 对应路径中与该边权值不同的最大权值,本次的答案即为原来 MST 的权值和减去该边的权值加上枚举的原本不在 MST 的边的权值,最终取答案最小值即可。

对于维护可以考虑用树剖 + 线段树,边权下放到点权,然后合并时可以强行讨论,也可无脑开 basic_string 排序后 unique 实现,此写法常数较大但可以通过。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

template < typename T = int >
inline T read(void);

int N, M;
struct Edge{
    Edge* nxt;
    int to;
    int val;
    OPNEW;
}ed[210000];
ROPNEW;
Edge* head[110000];

class UnionFind{
private:
    int fa[110000];
public:
    UnionFind(void){for(int i = 0; i <= 101000; ++i)fa[i] = i;}
    int Find(int x){return x == fa[x] ? x : fa[x] = Find(fa[x]);}
    void Union(int s, int t){int fs = Find(s), ft = Find(t); fa[fs] = ft;}
}uf;

struct Edg{int s, t, v;};
basic_string < Edg > edgs;
basic_string < Edg > trash;

int dep[110000], fa[110000], hson[110000], siz[110000], dfn[110000], idx[110000], top[110000];

void dfs_pre(int p = 1, int fa = 0){
    ::fa[p] = fa, dep[p] = dep[fa] + 1, siz[p] = 1;
    for(auto i = head[p]; i; i = i->nxt){
        if(SON == fa)continue;
        dfs_pre(SON, p);
        siz[p] += siz[SON];
        if(siz[SON] > siz[hson[p]])hson[p] = SON;
    }
}
void dfs_make(int p = 1, int top = 1){
    static int cdfn(0);
    dfn[p] = ++cdfn, idx[cdfn] = p, ::top[p] = top;
    if(hson[p])dfs_make(hson[p], top);
    for(auto i = head[p]; i; i = i->nxt)
        if(SON != fa[p] && SON != hson[p])dfs_make(SON, SON);
}

ll ans(LONG_LONG_MAX);
int val[110000];

void PushdownVal(int p = 1, int fa = 0){
    for(auto i = head[p]; i; i = i->nxt)
        if(SON != fa)
            val[SON] = i->val, PushdownVal(SON, p);
}

class SegTree{
private:
    int mx[110000 << 2], mx2[110000 << 2];
    #define LS (p << 1)
    #define RS (LS | 1)
    #define MID ((gl + gr) >> 1)
public:
    SegTree(void){memset(mx, -1, sizeof mx), memset(mx2, -1, sizeof mx2);}
    void Pushup(int p){
        basic_string < int > vals;
        if(~mx[LS])vals += mx[LS];
        if(~mx[RS])vals += mx[RS];
        if(~mx2[LS])vals += mx2[LS];
        if(~mx2[RS])vals += mx2[RS];
        sort(vals.begin(), vals.end(), greater < int >());
        vals.erase(unique(vals.begin(), vals.end()), vals.end());
        mx[p] = (int)vals.size() >= 1 ? *vals.begin() : -1;
        mx2[p] = (int)vals.size() >= 2 ? *next(vals.begin()) : -1;
    }
    void Build(int p = 1, int gl = 1, int gr = N){
        if(gl == gr)return mx[p] = val[idx[gl = gr]], void();
        Build(LS, gl, MID), Build(RS, MID + 1, gr);
        Pushup(p);
    }
    pair < int, int > Query(int l, int r, int p = 1, int gl = 1, int gr = N){
        if(l <= gl && gr <= r)return {mx[p], mx2[p]};
        if(l > gr || r < gl)return {-1, -1};
        basic_string < int > vals;
        auto ret = Query(l, r, LS, gl, MID);
        if(~ret.first)vals += ret.first;
        if(~ret.second)vals += ret.second;
        ret = Query(l, r, RS, MID + 1, gr);
        if(~ret.first)vals += ret.first;
        if(~ret.second)vals += ret.second;
        sort(vals.begin(), vals.end(), greater < int >());
        vals.erase(unique(vals.begin(), vals.end()), vals.end());
        return {(int)vals.size() >= 1 ? *vals.begin() : -1, (int)vals.size() >= 2 ? *next(vals.begin()) : -1};
    }
}st;

ll origin(0);

int QueryMx2(int s, int t, int ban){
    basic_string < int > vals;
    while(top[s] != top[t]){
        if(dep[top[s]] < dep[top[t]])swap(s, t);
        auto ret = st.Query(dfn[top[s]], dfn[s]);
        if(~ret.first)vals += ret.first;
        if(~ret.second)vals += ret.second;
        // printf("Querying %d->%d, [%d, %d], ret %d %d\n", top[s], s, dfn[top[s]], dfn[s], ret.first, ret.second);
        s = fa[top[s]];
    }if(dep[s] < dep[t])swap(s, t);
    auto ret = st.Query(dfn[hson[t]], dfn[s]);
    // printf("Querying %d->%d, [%d, %d], ret %d %d\n", hson[t], s, dfn[hson[t]], dfn[s], ret.first, ret.second);
    if(~ret.first)vals += ret.first;
    if(~ret.second)vals += ret.second;
    sort(vals.begin(), vals.end(), greater < int >());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    int mx = (int)vals.size() >= 1 ? *vals.begin() : -1, mx2 = (int)vals.size() >= 2 ? *next(vals.begin()) : -1;
    return mx != ban ? mx : mx2;
}

int main(){
    N = read(), M = read();
    for(int i = 1; i <= M; ++i){
        int s = read(), t = read(), v = read();
        if(s == t)continue;
        edgs += Edg{s, t, v};
    }sort(edgs.begin(), edgs.end(), [](const Edg &a, const Edg &b)->bool{return a.v < b.v;});
    for(auto edg : edgs){
        auto [s, t, v] = edg;
        if(uf.Find(s) != uf.Find(t))
            head[s] = new Edge{head[s], t, v},
            head[t] = new Edge{head[t], s, v},
            origin += v,
            uf.Union(s, t);
        else trash += edg;
    }dfs_pre(), dfs_make(), PushdownVal();
    st.Build();
    // printf("origin is %lld\n", origin);
    for(auto edg : trash){
        auto [s, t, v] = edg;
        int ret = QueryMx2(s, t, v);
        if(!~ret)continue;
        // printf("[%d - %d], v = %d, ret = %d\n", s, t, v, ret);
        ans = min(ans, origin - ret + v);
    }printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

LG-P3403 跳楼机

题面

给定 $ x, y, z, h $,求有多少 $ k \in [1, h] $ 满足 $ ax + by + cz = k $。

Solution

经典同余最短路问题,令 $ f(i) $ 表示由 $ y, z $ 凑成的模 $ x $ 余 $ i $ 的最小楼层,则有转移 $ f((i + y) \bmod x) = f(i) + y, f((i + z) \bmod x) = f(i) + z $,发现其满足最短路松弛操作的形式,直接以此建图跑一遍,每个 $ dis $ 对答案的贡献即为 $ \lfloor \dfrac{h - dis}{x} \rfloor + 1 $,最后的 $ +1 $ 则是取不选 $ x $ 的方案,同时注意判断每个是否满足 $ h \ge dis $。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

template < typename T = int >
inline T read(void);

ll H;
int x, y, z;

struct Edge{
    Edge* nxt;
    int to;
    int val;
    OPNEW;
}ed[210000];
ROPNEW;
Edge* head[110000];

bitset < 110000 > vis;
ll dis[110000];
ll ans(0);

void Dijkstra(void){
    memset(dis, 0x3f, sizeof dis);
    static priority_queue < pair < ll, int >, vector < pair < ll, int > >, greater < pair < ll, int > > > cur;
    dis[1] = 1, cur.push({0, 1});
    while(!cur.empty()){
        int p = cur.top().second; cur.pop();
        if(vis[p])continue;
        vis[p] = true;
        for(auto i = head[p]; i; i = i->nxt)
            if(dis[p] + i->val < dis[SON])
                dis[SON] = dis[p] + i->val, cur.push({dis[SON], SON});
    }
}

int main(){
    H = read < ll >();
    x = read(), y = read(), z = read();
    if(x == 1 || y == 1 || z == 1)printf("%lld\n", H), exit(0);
    for(int i = 0; i < x; ++i)
        head[i] = new Edge{head[i], (i + y) % x, y},
        head[i] = new Edge{head[i], (i + z) % x, z};
    Dijkstra();
    for(int i = 0; i < x; ++i)
        if(H >= dis[i])
            ans += (H - dis[i]) / x + 1;
    printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

UPD

update-2023_02_28 初稿

posted @ 2023-03-05 12:49  Tsawke  阅读(10)  评论(0编辑  收藏  举报