The 2024 ICPC Kunming Invitational Contest

B - Gold Medal

statements
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int n,k;
    cin>>n>>k;
    vector<int>a(n);
    int ans=0;
    for(int i=0;i<n;i++){
        cin>>a[i];
        ans+=a[i]/k;
        a[i]=a[i]%k;
    }
    sort(a.begin(),a.end(),greater<int>());
    int m;
    cin>>m;
    for(int i=0;i<n;i++){
        if(m+a[i]>=k){
            m-=k-a[i];
            ans++;
        }
    }
    ans+=m/k;
    cout<<ans<<"\n"; 
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;

}

G - Be Positive

statements
#include <iostream>
#include <bits/stdc++.h>
#define int long long
const int N=1e6+5;
using namespace std;
int a[N],b[N];
bool vis[N];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int sum=0;
    for(int i=0;i<N;i++){
        a[i]=i;
        b[i]=i;
    }
    for(int i=0;i<N-1;i++){
        sum=(sum^a[i]);
        if(sum==0){
            swap(b[i],b[i+1]);
            vis[i+1]=true;
        }
    }
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        if(vis[n]==true){
            cout<<"impossible\n";
        }
        else {
            for(int i=0;i<n;i++)cout<<b[i]<<" ";
            cout<<"\n";
        }
    }
    return 0;
}

I - Left Shifting 2

statements
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
bool vis[N];
int n;
int cal(string s){
    int res=0;
    int l=0,r=0;
    while(r<n){
        r=l;
        while(r+1<n&&s[l]==s[r+1]) r++;
        if(s[l]==s[r]){
            res+=(r-l+1)/2;
        }
        l=r+1;
    }
    return res;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        n=s.length();
        int pos=-1;
        if(s[0]==s[n-1]){
            for(int i=0;i<n;i++)
                if(s[i]==s[0]) pos=i;
                else break;
            if(pos==n-1){
                cout<<n/2<<'\n';
                continue ;
            }
        }
        string tmp;
        tmp=s.substr(pos+1,n)+s.substr(0,pos+1);
        int ans=cal(tmp);
        int l=0,r=0;
        int flag=0;
        while(r<n){
            r=l;
            while(r+1<n&&tmp[l]==tmp[r+1]) r++;
            if(tmp[l]==tmp[r]){
                int len=r-l+1;
                if(len%2==0) flag=1;
            }
            l=r+1;
        }
        cout<<ans-flag<<'\n';
    }
    return 0;
}

A - Two-star Contest

statements
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct node{
    int fi, se, s, id;
    node(): fi(0), se(0), s(0), id(0) {}
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<int>> p(n+1, vector<int>(m+1, 0));
    vector<node> info(n+1);
    vector<int> idd(n+1,0);
    for(int i=1;i<=n;i++){
        cin>>info[i].s;
        info[i].fi = 0;
        info[i].se = 0;
        for(int j=1;j<=m;j++){
            cin>>p[i][j];
            if(p[i][j] != -1) info[i].fi += p[i][j];
            else info[i].se++;
        }
        info[i].id = i;
    }

    sort(info.begin()+1, info.end(), [&](const node &a, const node &b){
        return a.s > b.s;
    });
    for(int i=1;i<=n;i++) idd[info[i].id] = i;

    const long long INF = (long long)9e18;
    long long prev_min = INF; // 所有下一组值都必须 < prev_min

    vector<int> ans(n+1, 0);

    int i = 1;
    while(i <= n){
        int j = i;
        while(j <= n && info[j].s == info[i].s) j++;
        // group is [i, j-1]
        // For each member compute its max, and assign limit = min(max, prev_min-1)
        long long group_min_assigned = INF;
        // First pass: check feasibility
        for(int t = i; t < j; t++){
            long long maxv = info[t].fi + info[t].se * (long long)k;
            long long limit = min(maxv, prev_min - 1);
            if(limit < info[t].fi){
                cout << "No\n";
                return;
            }
        }
        // Second pass: actually assign
        for(int t = i; t < j; t++){
            long long maxv = info[t].fi + info[t].se * (long long)k;
            long long limit = min(maxv, prev_min - 1);
            ans[info[t].id] = (int)limit;
            if(limit < group_min_assigned) group_min_assigned = limit;
        }
        // update prev_min for next lower-s groups
        prev_min = group_min_assigned;
        i = j;
    }

    // 填回缺失值(按原行顺序)
    for(int r = 1; r <= n; r++){
        int idx = idd[r]; // 在排序后的 info 中的索引
        for(int c = 1; c <= m; c++){
            if(p[r][c] == -1){
                if(info[idx].fi == ans[r]){
                    p[r][c] = 0;
                } else if(info[idx].fi + k <= ans[r]){
                    info[idx].fi += k;
                    p[r][c] = k;
                } else {
                    p[r][c] = ans[r] - info[idx].fi;
                    info[idx].fi = ans[r];
                }
            }
        }
    }

    cout << "Yes\n";
    for(int r = 1; r <= n; r++){
        for(int c = 1; c <= m; c++){
            cout << p[r][c] << (c==m?'\n':' ');
        }
    }
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}

参考代码

#include <bits/stdc++.h>
using i64 = long long;
void Solve() {
    int n, m;
    i64 K;
    std::cin >> n >> m >> K;
    std::vector<int> c(n);
    std::vector<i64> s(n);
    std::map<int, std::vector<int>> adj;
    std::vector a(n, std::vector<int>(m));
    for (int i = 0; i < n; ++i) {
        int x;
        std::cin >> x;
        adj[x].push_back(i);
        int cnt = 0;
        i64 sum = 0;        
        for (int j = 0; j < m; ++j) {
            std::cin >> a[i][j];
            if (a[i][j] == -1) {
                ++cnt;
            } else {
                sum += a[i][j];
            }
        }
        c[i] = cnt;
        s[i] = sum;
    }
    i64 last = 0;
    for (auto [_, vec] : adj) {
        i64 Min = last, Max = 1e18;
        for (int i : vec) {
            Min = std::max(Min, s[i]);
            Max = std::min(Max, s[i] + c[i] * K);
        }
        if (Max < last) {
            std::cout << "No" << "\n";
            return;
        }
        for (int i : vec) {
            i64 rest = std::min(s[i] + c[i] * K, Min) - s[i];
            for (int j = 0; j < m; ++j) {
                if (a[i][j] == -1) {
                    i64 d = std::min(rest, K);
                    a[i][j] = d;
                    rest -= d;
                }
            }
        }
        last = Min + 1;
        // std::cerr << Min << ' ' << Max << '\n';
    }
    std::cout << "Yes" << "\n";
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            std::cout << a[i][j] << ' ';
        }
        std::cout << '\n';
    }
}
int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int t;
    std::cin >> t;
    for (int ti = 1; ti <= t; ++ti) {
        // std::cerr << "Solve : " << ti << '\n';
        Solve(); 
    }
    return 0;
}

E - Relearn through Review

statements
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n,k;
        cin>>n>>k;
        vector<int> a(n+2,0);
        vector<int> g(n+2,0);
        vector<int> suf(n+2,0);
        for(int i=1;i<=n;i++){
            cin>>a[i];
            g[i]=__gcd(g[i-1],a[i]);
        }
        for(int i=n;i>=1;i--) suf[i]=__gcd(suf[i+1],a[i]);
        int ans=g[n];
        for(int i=1;i<=n;i++){
            if(g[i]!=g[i-1]){
                int gc=g[i-1];
                for(int j=i;j<=n;j++){
                    gc=__gcd(gc,a[j]+k);
                    ans=max(ans,__gcd(gc,suf[j+1]));
                }
            }
        }
        cout<<ans<<'\n';
    }
    return 0;
}

H - Subarray

statements
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int MOD = 998244353;
const int G = 3;

ll mod_pow(ll a, ll b){
    ll r = 1;
    while(b){
        if(b & 1) r = r * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return r;
}
ll mod_inv(ll a){ return mod_pow(a, MOD-2); }

void ntt(vector<ll>& a, bool invert){
    int n = (int)a.size();
    // bit reversal
    for (int i = 1, j = 0; i < n; i++){
        int bit = n >> 1;
        for (; j & bit; bit >>= 1) j ^= bit;
        j ^= bit;
        if (i < j) swap(a[i], a[j]);
    }
    for (int len = 2; len <= n; len <<= 1){
        ll wlen = mod_pow(G, (MOD - 1) / len);
        if (invert) wlen = mod_inv(wlen);
        for (int i = 0; i < n; i += len){
            ll w = 1;
            for (int j = 0; j < len/2; j++){
                ll u = a[i+j];
                ll v = a[i+j+len/2] * w % MOD;
                a[i+j] = (u + v) % MOD;
                a[i+j+len/2] = (u - v + MOD) % MOD;
                w = w * wlen % MOD;
            }
        }
    }
    if (invert){
        ll inv_n = mod_inv(n);
        for (ll &x : a) x = x * inv_n % MOD;
    }
}

vector<ll> multiply(const vector<ll>& A, const vector<ll>& B){
    if (A.empty() || B.empty()) return {};
    vector<ll> fa(A.begin(), A.end()), fb(B.begin(), B.end());
    int n = 1;
    while (n < (int)(A.size() + B.size())) n <<= 1;
    fa.resize(n); fb.resize(n);
    ntt(fa, false); ntt(fb, false);
    for (int i = 0; i < n; i++) fa[i] = fa[i] * fb[i] % MOD;
    ntt(fa, true);
    return fa;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    if (!(cin >> T)) return 0;
    while (T--){
        int n;
        cin >> n;
        vector<ll> a(n);
        for (int i = 0; i < n; i++) cin >> a[i];

        // prev greater (strict) and next greater (strict)
        vector<int> left(n), right(n);
        stack<int> st;
        for (int i = 0; i < n; i++){
            while (!st.empty() && a[st.top()] <= a[i]) st.pop();
            left[i] = st.empty() ? -1 : st.top();
            st.push(i);
        }
        while (!st.empty()) st.pop();
        for (int i = n-1; i >= 0; i--){
            while (!st.empty() && a[st.top()] <= a[i]) st.pop();
            right[i] = st.empty() ? n : st.top();
            st.push(i);
        }

        // group by (left, right, value)
        // key: tuple<int,int,ll>
        unordered_map<long long, vector<int>> groups;
        groups.reserve(n * 2);
        // encode triple into 64-bit key: L (20 bits) | R (20 bits) | hashed value low 24 bits
        // careful about collisions; a safer map<tuple,..> is slower; using unordered_map with a combined key is acceptable here.
        // We'll use a robust encoding assuming n <= 2e5 and values fit in 32-bit.
        auto make_key = [&](int L, int R, ll v)->long long{
            // shift L and R to non-negative
            long long Lp = (long long)(L + 1); // L in [-1..n-1] -> [0..n]
            long long Rp = (long long)R;      // R in [0..n]
            // Use 21 bits for Lp and 21 bits for Rp (supports n up to ~2e6). Remaining bits for value hashed.
            long long key = (Lp << 42) ^ (Rp << 21) ^ ( (long long)( (v ^ (v >> 32)) & ((1<<21)-1) ) );
            return key;
        };

        for (int i = 0; i < n; i++){
            long long key = make_key(left[i], right[i], a[i]);
            groups[key].push_back(i);
        }

        vector<ll> ans(n+1, 0);

        for (auto &kv : groups){
            vector<int>& pos = kv.second;
            if (pos.empty()) continue;
            sort(pos.begin(), pos.end());
            int m = (int) pos.size(); // occurrences count
            // build t of length m+1, t0 = pos[0] - left[pos[0]] , t_j = pos[j] - pos[j-1], t_m = right[pos[m-1]] - pos[m-1]
            vector<ll> t;
            t.reserve(m+1);
            int first = pos[0];
            int Lg = left[first];
            t.push_back( (ll)first - (ll)Lg ); // = g0+1
            for (int j = 1; j < m; j++){
                t.push_back( (ll)pos[j] - (ll)pos[j-1] ); // g_j + 1
            }
            int last = pos.back();
            int Rg = right[last];
            t.push_back( (ll)Rg - (ll)last ); // = g_m + 1

            // convolution with reversed t
            vector<ll> treg = t;
            reverse(treg.begin(), treg.end());
            vector<ll> conv = multiply(t, treg);
            // conv length >= 2*(m+1)-1

            // For k = 1..m, contribution is C_{m - k}
            // Here m_occ = m, conv index = m - k
            for (int k = 1; k <= m; k++){
                int idx = m - k;
                if (0 <= idx && idx < (int)conv.size()){
                    ans[k] = (ans[k] + conv[idx]) % MOD;
                }
            }
        }
        int res=0;
        for (int k = 1; k <= n; k++){
            res+=ans[k]*ans[k]%MOD*k%MOD;
            res%=MOD;
        }
        cout << res<< '\n';
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容