ACM-ICPC 2018 焦作赛区网络预赛

ACM-ICPC 2018 焦作赛区网络预赛

\(A. Magic Mirror\)
签到

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
int main(){
    int T;
    for(cin >> T; T; T--){
        string s;
        cin >> s;
        for(int i = 0; i < (int)s.length(); i++) s[i] = tolower(s[i]);
        if(s=="jessie") cout << "Good guy!" << endl;
        else cout << "Dare you say that again?" << endl;
    }
    return 0;
}

\(B. Mathematical Curse\)
\(dp[i][j]\)表示当前到第\(i\)个巫师,消除标记到\(j\)的最大值和最小值
因为有正有负,两个负数相乘变成正数可能变化比较大,所以要存正负的极值

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
using LL = int_fast64_t;
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL ope(LL x, char op, LL y){
    if(op=='-') return x - y;
    if(op=='+') return x + y;
    if(op=='*') return x * y;
    return x / y;
}
char s[MAXN];
LL f[2][MAXN][6];
int n,m,A[MAXN],K;
void solve(){
    cin >> n >> m >> K;
    memset(f[0],0x3f,sizeof(f[0]));
    memset(f[1],-0x3f,sizeof(f[1]));
    for(int i = 0; i <= n; i++) f[0][i][0] = f[1][i][0] = K;
    for(int i = 1; i <= n; i++) cin >> A[i];
    cin >> (s+1);
    for(int i = 1; i <= n; i++) for(int j = 1; j <= min(i,m); j++){
        f[0][i][j] = f[0][i-1][j];
        f[1][i][j] = f[1][i-1][j];
        if(f[0][i-1][j-1]!=INF){
            f[0][i][j] = min(f[0][i][j],ope(f[0][i-1][j-1],s[j],A[i]));
            f[1][i][j] = max(f[1][i][j],ope(f[0][i-1][j-1],s[j],A[i]));
        }
        if(f[1][i-1][j-1]!=-INF){
            f[0][i][j] = min(f[0][i][j],ope(f[1][i-1][j-1],s[j],A[i]));
            f[1][i][j] = max(f[1][i][j],ope(f[1][i-1][j-1],s[j],A[i]));
        }
    }
    LL ret = -INF;
    for(int i = m; i <= n; i++) ret = max(ret,f[1][i][m]);
    cout << ret << endl;
}
int main(){
    int T;
    ____();
    for(cin >> T; T; T--) solve();    
    return 0;
}

\(C. Password\)

\(D. Sequence\)

\(E. Jiu Yuan Wants to Eat\)
如果只有\(1,2,4\)操作那就是树剖的模板题了,现在多了一个操作\(3\)
其实还是模板题,因为是对\(2^{64}\)取模,那么每个数按位取反就相当于每个数被\(2^{64}-1\)减,那就相当于每个数先减去\(2^{64}-1\)然后再取负,那么这题就出来了

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
using ull = uint_fast64_t;
const int MAXN = 1e5+7;
struct SegmentTree{
    ull w[MAXN<<2],lmul[MAXN<<2],ladd[MAXN<<2];
    int l[MAXN<<2],r[MAXN<<2];
    #define ls(rt) rt << 1
    #define rs(rt) rt << 1 | 1
    #define pushup(rt) w[rt] = w[ls(rt)] + w[rs(rt)]
    void build(int L, int R, int rt = 1){
        l[rt] = L, r[rt] = R; w[rt] = 0ull;
        lmul[rt] = 1ull; ladd[rt] = 0ull;
        if(L+1==R) return;
        int mid = (L + R) >> 1;
        build(L,mid,ls(rt)); build(mid,R,rs(rt));
    }
    void pushdown(int rt){
        if(lmul[rt]!=1ull){
            lmul[ls(rt)] *= lmul[rt]; ladd[ls(rt)] *= lmul[rt]; w[ls(rt)] *= lmul[rt];
            lmul[rs(rt)] *= lmul[rt]; ladd[rs(rt)] *= lmul[rt]; w[rs(rt)] *= lmul[rt];
            lmul[rt] = 1ull;
        }
        if(ladd[rt]){
            ladd[ls(rt)] += ladd[rt];
            ladd[rs(rt)] += ladd[rt];
            w[ls(rt)] += ladd[rt] * (r[ls(rt)] - l[ls(rt)]);
            w[rs(rt)] += ladd[rt] * (r[rs(rt)] - l[rs(rt)]);
            ladd[rt] = 0ull;
        }
    }
    void update(int L, int R, int op, ull x, int rt = 1){
        if(l[rt]>=R or L>=r[rt]) return;
        if(L<=l[rt] and r[rt]<=R){
            if(op==3){
                w[rt] -= -1ull * (r[rt] - l[rt]);
                ladd[rt] -= -1ull;
                w[rt] = -w[rt], lmul[rt] = -lmul[rt], ladd[rt] = -ladd[rt];
            }
            else if(op==2) w[rt] += x * (r[rt] - l[rt]), ladd[rt] += x;
            else if(op==1) w[rt] *= x, ladd[rt] *= x, lmul[rt] *= x;
            return;
        }
        pushdown(rt);
        update(L,R,op,x,ls(rt)); update(L,R,op,x,rs(rt));
        pushup(rt);
    }
    ull qsum(int L, int R, int rt = 1){
        if(l[rt]>=R or L>=r[rt]) return 0;
        if(L<=l[rt] and r[rt]<=R) return w[rt];
        pushdown(rt);
        return qsum(L,R,ls(rt)) + qsum(L,R,rs(rt));
    }
}ST;
int n,m,dfn[MAXN],num,tp[MAXN],sz[MAXN],son[MAXN],depth[MAXN],par[MAXN];
vector<int> G[MAXN];
void dfs1(int u){
    depth[u] = depth[par[u]] + 1;
    sz[u] = 1; son[u] = 0;
    for(int v : G[u]){
        dfs1(v);
        sz[u] += sz[v];
        if(sz[son[u]]<sz[v]) son[u] = v;
    }
}
void dfs2(int u, int top){
    tp[u] = top;
    dfn[u] = ++num;
    if(son[u]) dfs2(son[u],top);
    for(int v : G[u]){
        if(v==son[u]) continue;
        dfs2(v,v);
    }
}
void modify(int u, int v, int op, ull x = 0ull){
    while(tp[u]!=tp[v]){
        if(depth[tp[u]]<depth[tp[v]]) swap(u,v);
        ST.update(dfn[tp[u]],dfn[u]+1,op,x);
        u = par[tp[u]];
    }
    if(depth[u]<depth[v]) swap(u,v);
    ST.update(dfn[v],dfn[u]+1,op,x);
}
ull qsum(int u, int v){
    ull ret = 0;
    while(tp[u]!=tp[v]){
        if(depth[tp[u]]<depth[tp[v]]) swap(u,v);
        ret += ST.qsum(dfn[tp[u]],dfn[u]+1);
        u = par[tp[u]];
    }
    if(depth[u]<depth[v]) swap(u,v);
    return ret + ST.qsum(dfn[v],dfn[u]+1);
}
int main(){
    while(scanf("%d",&n)!=EOF){
        num = 0;
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 2; i <= n; i++){
            scanf("%d",&par[i]);
            G[par[i]].push_back(i);
        }
        dfs1(1); dfs2(1,1);
        ST.build(1,n+1);
        scanf("%d",&m);
        while(m--){
            int op; scanf("%d",&op);
            if(op<=2){
                int u, v; ull x;
                scanf("%d %d %llu",&u,&v,&x);
                modify(u,v,op,x);
            }
            else if(op==3){
                int u, v;
                scanf("%d %d",&u,&v);
                modify(u,v,op);
            }
            else{
                int u, v;
                scanf("%d %d",&u,&v);
                printf("%llu\n",qsum(u,v));
            }
        }
    }
    return 0;
}

\(F. Modular Production Line\)
K次区间覆盖问题,边权取负最小费用流

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
const int INF = 0x3f3f3f3f;
#define S 0
#define T MAXN - 1
int k,m,n,flow[MAXN],dist[MAXN],pre[MAXN],preid[MAXN],vis[MAXN];
pair<pair<int,int>,int> work[MAXN];
struct EDGE{
    int to,cap,fee,rev;
    EDGE(){}
    EDGE(int _to, int _cap, int _fee, int _rev){
        to = _to; cap = _cap;
        fee = _fee; rev = _rev;
    }
};
vector<EDGE> G[MAXN];
void ADDEDGE(int u, int v, int cap, int fee){
    G[u].emplace_back(EDGE(v,cap,fee,(int)G[v].size()));
    G[v].emplace_back(EDGE(u,0,-fee,(int)G[u].size()-1));
}
void build(){
    for(int i = 0; i < MAXN; i++) G[i].clear();
    for(int i = 0; i < n; i++) ADDEDGE(i,i+1,k,0);
    ADDEDGE(n,T,k,0);
    for(int i = 1; i <= m; i++) ADDEDGE(work[i].first.first,work[i].first.second,1,-work[i].second);
}
bool spfa(){
    memset(dist,0x3f,sizeof(dist));
    dist[S] = 0;
    flow[S] = INF;
    memset(vis,0,sizeof(vis));
    queue<int> que;
    que.push(S);
    while(!que.empty()){
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for(int i = 0; i < (int)G[u].size(); i++){
            auto e = G[u][i];
            if(!e.cap or dist[e.to]<=dist[u]+e.fee) continue;
            dist[e.to] = dist[u] + e.fee;
            flow[e.to] = min(e.cap,flow[u]);
            pre[e.to] = u; preid[e.to] = i;
            if(!vis[e.to]){
                vis[e.to] = 1;
                que.push(e.to);
            }
        }
    }
    return dist[T]!=INF;
}
int mcmf(){
    int cost = 0;
    while(spfa()){
        int u = T;
        cost += dist[T] * flow[T];
        while(u!=S){
            int p = pre[u], id = preid[u];
            G[p][id].cap -= flow[T];
            G[u][G[p][id].rev].cap += flow[T];
            u = pre[u];
        }
    }
    return cost;
}
void solve(){
    cin >> n >> k >> m;
    vector<int> vec;
    for(int i = 1; i <= m; i++){
        cin >> work[i].first.first >> work[i].first.second >> work[i].second;
        work[i].first.second++;
        vec.push_back(work[i].first.first); vec.push_back(work[i].first.second);
    }
    sort(vec.begin(),vec.end());
    vec.erase(unique(vec.begin(),vec.end()),vec.end());
    for(int i = 1; i <= m; i++){
        work[i].first.first = lower_bound(vec.begin(),vec.end(),work[i].first.first) - vec.begin() + 1;
        work[i].first.second = lower_bound(vec.begin(),vec.end(),work[i].first.second) - vec.begin() + 1;
    }
    n = vec.size();
    build();
    cout << -mcmf() << endl;
}
int main(){
    int t;
    ____();
    for(cin >> t; t; t--) solve();    
    return 0;
}

\(G. Give Candies\)
计算\(2^n\),利用费马小定理降幂,然后快速幂

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
const int MAXN = 2e5+7;
typedef long long int LL;
const LL MOD = 1e9+7;
char s[MAXN];
LL qpow(LL a, LL b){
    LL ret = 1;
    while(b){
        if(b&1) ret = ret * a % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return ret;
}
void solve(){
    cin >> s;
    LL pw = 0;
    for(int i = 0, len = strlen(s); i < len; i++) pw = (pw*10+s[i]-'0')%(MOD-1);
    pw = (pw-1+MOD)%MOD;
    cout << qpow(2,pw) << endl;
}
int main(){
    ____();
    int T;
    for(cin >> T; T; T--) solve();
    return 0;
}

\(H. String and Times\)
SAM,找\(right\)集合大小在\([L,R]\)的子串有多少个

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 4e5+7;
struct SAM{
    int tot,ch[MAXN][26],link[MAXN],last,cnt[MAXN],c[MAXN],sa[MAXN],len[MAXN];
    void clear(){ last = tot = 1; memset(ch[tot],0,sizeof(ch[tot])); link[1] = 0; cnt[1] = 0; }
    int newnode(){ tot++; memset(ch[tot],0,sizeof(ch[tot])); cnt[tot] = 0; return tot; }
    void extend(char car){
        int c = car - 'A';
        int np = newnode(), p = last;
        len[np] = len[last] + 1; cnt[np] = 1;
        while(p and !ch[p][c]){
            ch[p][c] = np;
            p = link[p];
        }
        if(!p) link[np] = 1;
        else{
            int q = ch[p][c];
            if(len[p]+1==len[q]) link[np] = q;
            else{
                int clone = newnode();
                link[clone] = link[q];
                memcpy(ch[clone],ch[q],sizeof(ch[q]));
                len[clone] = len[p] + 1;
                while(p and ch[p][c]==q){
                    ch[p][c] = clone;
                    p = link[p];
                }
                link[q] = link[np] = clone;
            }
        }
        last = np;
    }
    long long int query(int L, int R){
        for(int i = 0; i <= tot; i++) c[i] = 0;
        for(int i = 1; i <= tot; i++) c[len[i]]++;
        for(int i = 1; i <= tot; i++) c[i] += c[i-1];
        for(int i = tot; i >= 1; i--) sa[c[len[i]]--] = i;
        for(int i = tot; i >= 1; i--){
            int u = sa[i];
            cnt[link[u]] += cnt[u];
        }
        long long int ret = 0;
        for(int i = 2; i <= tot; i++) if(cnt[i]>=L and cnt[i]<=R) ret += len[i] - len[link[i]];
        return ret;
    }
}sam;
char s[MAXN];
int main(){
    while(scanf("%s",s)!=EOF){
        int l, r;
        scanf("%d %d",&l,&r);
        sam.clear();
        for(int i = 0, len = strlen(s); i < len; i++) sam.extend(s[i]);
        printf("%lld\n",sam.query(l,r));
    }
    return 0;
}

\(I. Save the Room\)
签到

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
int main(){
    int a,b,c;
    while(cin >> a >> b >> c){
        if((a&1) and (b&1) and (c&1)) cout << "No" << endl;
        else cout << "Yes" << endl;
    }
    return 0;
}

\(J. Participate in E-sports\)

\(K. Transport Ship\)
二进制拆解+完全背包

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const int MAXN = 1e4+7;
const LL MOD = 1e9+7;
int n,q,Q[MAXN],f[MAXN];
vector<int> vec;
void solve(){
    scanf("%d %d",&n,&q);
    vec.clear();
    for(int i = 1; i <= n; i++){
        int v, c;
        scanf("%d %d",&v,&c);
        c = (1<<c) - 1;
        for(int bit = 0; c&(1<<bit); bit++) vec.emplace_back(v*(1<<bit));
    }
    memset(f,255,sizeof(f));
    for(int i = 1; i <= q; i++) scanf("%d",&Q[i]);
    int maxx = *max_element(Q+1,Q+1+q);
    f[0] = 1;
    for(int p : vec){
        for(int i = maxx; i >= p; i--){
            if(f[i-p]!=-1){
                if(f[i]==-1) f[i] = f[i-p];
                else f[i] = (f[i]+f[i-p])%MOD;
            }
        }
    }
    for(int i = 1; i <= q; i++) printf("%d\n",(f[Q[i]]==-1?0:f[Q[i]]));
}
int main(){
    int T;
    for(scanf("%d",&T); T; T--) solve();
    return 0;
}

\(L. Poor God Water\)
矩阵快速幂优化DP
把三种东西看作\(A,B,C\),然后两两组合,构造一个\(9\cdot 9\)的矩阵来求解

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
typedef long long int LL;
const LL MOD = 1e9+7;
struct Matrix{
    LL m[9][9];
    Matrix(int tag = 0){
        for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++){
            if(i==j) m[i][j] = tag;
            else m[i][j] = 0;
        }
    }
    void set(int x, int y){ m[x][y] = 1; }
    Matrix operator * (const Matrix rhs){
        Matrix ret(0);
        for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++){
            for(int k = 0; k < 9; k++) ret.m[i][j] = (ret.m[i][j] + m[i][k] * rhs.m[k][j]) %MOD;
        }
        return ret;
    }
};
Matrix qpow(Matrix A, LL b){
    Matrix ret(1);
    while(b){
        if(b&1) ret = ret * A;
        b >>= 1;
        A = A * A;
    }
    return ret;
}
LL n;
Matrix init(0);
void solve(){
    cin >> n;
    if(n==1){
        cout << 3 << endl;
        return;
    }
    Matrix ret = qpow(init,n-2);
    LL res = 0;
    for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++) res = (res + ret.m[i][j]) % MOD;
    cout << res << endl;
}
int main(){
    ____();
    init.set(0,1); init.set(0,2);
    init.set(1,3); init.set(1,4);
    init.set(2,6); init.set(2,7); init.set(2,8);
    init.set(3,0); init.set(3,2);
    init.set(4,3); init.set(4,5);
    init.set(5,6); init.set(5,8);
    init.set(6,0); init.set(6,1); init.set(6,2);
    init.set(7,4); init.set(7,5);
    init.set(8,6); init.set(8,7);
    int T; for(cin >> T; T; T--) solve();    
    return 0;
}
posted @ 2020-04-28 00:41  _kiko  阅读(133)  评论(0编辑  收藏  举报