Loading

USACO Bronze All Kill & Solutions

EFB815B3EED031FDB41118340053F0E0

Preface

After four hours of thinking, the rain didn’t feel like noise anymore—it felt like proof that time was still moving. I finished the last USACO Bronze contest with full score (1000/1000), then spent the remaining hour peeking into Silver, letting harder ideas drift past without forcing them to land. When the screen finally dimmed, I took a real break. What follows is a write-up of all three Bronze problems: the clean solutions, the messy detours (TLE, WA, and why), and the small habits that kept me steady—one raindrop at a time.

When I closed the last tab, the rain was still there—but it no longer sounded like pressure. It sounded like relief. The earlier rounds didn’t vanish, and I didn’t need them to. They became the reason this clean sweep mattered: not as a trophy, but as a turning point. I looked at Silver, let myself be curious instead of afraid, and then I rested—properly. If you take anything from these notes, let it be this: mistakes aren’t the opposite of progress; they’re the proof that you stayed in the storm long enough to learn the weather.


Solutions

A. Greedy by Residue Buckets (from a hash trap to a robust \(O(n\log n)\))

A natural first attempt is to maintain a hash set of used final values: for each number, while it collides, keep applying \(\pm k\) until it becomes unused, then insert it. This may look fast on random data, but the worst case is bad: if many numbers lie in the same reachable chain (same residue class), the \(i\)-th insertion can require \(\Theta(i)\) retries, so the total retries become \(0+1+\cdots+(n-1)=\Theta(n^2)\), which can TLE.

We need a guaranteed bound. Let \(d=|k|\). The key invariant is that adding/subtracting \(k\) never changes a number’s residue modulo \(d\). Therefore, collisions can only happen inside the same residue class. We bucket all numbers by

\[r \equiv a \pmod d,\qquad r\in{0,1,\dots,d-1}. \]

Inside one bucket (fixed \(r\)), every number can be written as

\[a = r + d\cdot b \]

for some integer \(b\). One operation \(\pm k\) corresponds to changing \(b\) by \(\pm 1\) (up to a sign when \(k<0\), which can be unified by multiplying \(b\) with \(\mathrm{sgn}(k)\)). Thus each bucket becomes a one-dimensional problem: given a multiset of integers \(x\), increase some values so that all become distinct, minimizing the total increment.

For one bucket, sort its values \(x\) increasingly and scan from left to right. Maintain \(\mathrm{prev}\) as the last fixed value. For each \(x\):

  • if \(x>\mathrm{prev}\), keep it;
  • otherwise we must raise it to \(\mathrm{prev}+1\), add \((\mathrm{prev}+1-x)\) to the answer, and set \(x\leftarrow \mathrm{prev}+1\).
    This is optimal because when \(x\le \mathrm{prev}\), any valid final value must be at least \(\mathrm{prev}+1\), and choosing exactly \(\mathrm{prev}+1\) is the minimum possible cost at this step (choosing larger only increases cost and cannot help future steps).

The total complexity is \(O(n\log n)\) due to sorting across buckets.

Accepted Code (C++17)

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define i128 __int128
#define ld long double
#define fir first
#define sec second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lowbit(x) (x&-x)
using namespace std;
const int MOD=998244353;
const int MOD1=1e9+7;
//char ibuf[1<<25],*p1=buf,*p2=buf;
mt19937 mrand(random_device{}());
int rnd(int x){ return mrand() % x;}
ll qpow(ll a,ll b){ll res=1;while(b){if(b&1)res=res*a%MOD;a=a*a%MOD,b>>=1;}return res;}
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}  
ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}
//C++ 17 -O2
//By MaZhaoze
int main(){
	ios::sync_with_stdio(0);
    cin.tie(0);
	int t;
	cin>>t;
	while(t--){
		int n;
        ll k,ans=0;
        cin>>n>>k;
        if(n==1){
            ll x; 
			cin>>x;
            cout<<0<<'\n';
            continue;
        }
        ll d = llabs(k);
        int s;
		if(k>0) s = 1;
		else s = -1;    
        vector<vector<ll>> f(d);
		for(int i=0;i<n;i++){
			ll cwd;
            cin>>cwd;
            ll r=cwd%d;              
            ll b=(cwd-r)/d;        
            ll x=(ll)s*b;            
            f[r].push_back(x);
		}
		for(auto &v:f){
			if(v.empty()) continue;
			sort(v.begin(),v.end());
			ll p = (ll)-4e18;
            for(ll x:v){
                if(x <= p){
                    ans+=(p+1-x);
                    x=p+1;
                }
                p = x;
            }
		}
		cout<<ans<<'\n';
	}
	return 0;
}

B. Parity \(\rightarrow\) Bitstring, then compute \(B\) and \(\lfloor B/2\rfloor\)

The whole transformation only depends on the parity of each character, so we first normalize the input into a binary string and then evaluate it as a binary number.

Let the input be a string \(s\) of length \(n\), and let \(M = 10^9+7\). Define

\[\text{temp}= \begin{cases} 0, & \text{if } s_i\in{0,1}\ \forall i,\ 1, & \text{otherwise.} \end{cases} \]

Construct a bitstring \(b\in{0,1}^n\) as follows: if \(\text{temp}=0\), take \(b=s\); otherwise map each digit to parity,

\[b_i \equiv (s_i-\text{'0'}) \bmod 2. \]

Now remove leading zeros: let \(p\) be the smallest index such that \(b_p=1\). If no such \(p\) exists (i.e., \(b\) is all zeros), then the answer is simply

\[\text{ans}\equiv \text{temp}\pmod M. \]

Otherwise, interpret the suffix \(b_p b_{p+1}\dots b_{n-1}\) as a binary integer. Define

\[B \equiv \sum_{i=p}^{n-1} b_i\cdot 2^{,n-1-i}\pmod M, \qquad B_h \equiv \sum_{i=p}^{n-2} b_i\cdot 2^{,n-2-i}\pmod M. \]

In ordinary integer arithmetic, \(B_h=\left\lfloor \frac{B}{2}\right\rfloor\) because dropping the last bit is exactly a right shift by one. A crucial pitfall is that modular division does not represent floor:

\[\left\lfloor \frac{B}{2}\right\rfloor \not\equiv B\cdot 2^{-1}\pmod M, \]

so \(B_h\) must be computed directly from the prefix bits (or equivalently, from the same scan).

We compute \(B\) and \(B_h\) in one left-to-right pass:
initialize \(B=0\), \(B_h=0\), then for \(i=p,\dots,n-1\) do

\[B \leftarrow (2B + b_i)\bmod M, \]

and if \(i<n-1\) also do

\[B_h \leftarrow (2B_h + b_i)\bmod M. \]

Finally output

\[\text{ans}\equiv \text{temp} + B + B_h \pmod M. \]

Complexity. Each test case performs only a constant number of linear scans over the string (check whether binary, build \(b\), skip leading zeros, and compute \(B,B_h\)), so the time complexity is \(O(\sum n)\) and the memory usage is \(O(n)\).

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define i128 __int128
#define ld long double
#define fir first
#define sec second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lowbit(x) (x&-x)
using namespace std;
const int MOD=998244353;
const int MOD1=1e9+7;
//char ibuf[1<<25],*p1=buf,*p2=buf;
mt19937 mrand(random_device{}());
int rnd(int x){ return mrand() % x;}
ll qpow(ll a,ll b){ll res=1;while(b){if(b&1)res=res*a%MOD;a=a*a%MOD,b>>=1;}return res;}
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}  
ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}
//C++ 17 -O2
//By MaZhaoze
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        int temp=0;
        for(char c:s){
            if(c!='0'&&c!='1'){
                temp = 1;
                break;
            }
        }
        string bit;
        bit.reserve(s.size());
        if(temp){
            for(char c:s){
                int d=c-'0';
                if(d&1)bit.push_back('1');
                else bit.push_back('0');
            }
        }else{
            bit = s;
        }
        int p=0,n=bit.size();
        while(p<n&&bit[p]=='0')p++;
        if(p==n){
            cout<<(temp%MOD1)<<'\n';
            continue;
        }
        ll B=0,Bh=0;
        for(int i=p;i<n;i++){
            int b=bit[i]-'0';
            B=(B*2+b)%MOD1;
            if(i<n-1){
                Bh =(Bh*2+b)%MOD1;
            }
        }
        ll ans=temp;
        ans+=B;
        ans+=Bh;
        ans%=MOD1;
        cout<<ans<<'\n';
    }
    return 0;
}

C. Constructive: Fix \(a_0\) from left to right using swaps

We are given a target string \(t\) of length \(m\) and \(n\) strings \(a_0,a_1,\dots,a_{n-1}\) (each length \(m\)). There are two operations:

  • Type \(1\): swap two positions inside the same string, i.e. swap \(a_x[i]\) and \(a_x[j]\).
  • Type \(2\): swap characters in the same column between two strings, i.e. swap \(a_x[i]\) and \(a_y[i]\).

A simple constructive strategy is to treat \(a_0\) as a “workspace” and make it equal to \(t\) one position at a time. We process indices \(i=0,1,\dots,m-1\) and maintain the invariant:

After finishing position \(i\), we have \(a_0[0..i]=t[0..i]\), and we will never modify this prefix again.

At each position \(i\):

If \(a_0[i]=t[i]\), do nothing.

Otherwise, we first try to fix it using only a Type \(1\) swap inside \(a_0\): search for some \(j\ge i\) such that \(a_0[j]=t[i]\). If found, swap \(a_0[i]\) and \(a_0[j]\) (Type \(1\)), and position \(i\) is fixed.

If \(a_0\) does not contain \(t[i]\) in \([i,m-1]\), we fetch it from another string. We search for some string index \(x\in{1,\dots,n-1}\) and some column \(y\in{0,\dots,m-1}\) such that \(a_x[y]=t[i]\). If found, we “move” that character to column \(i\) inside \(a_x\) (if needed) and then bring it into \(a_0\):

  • If \(y\ne i\), do a Type \(1\) swap inside \(a_x\) between positions \(i\) and \(y\), so that \(a_x[i]=t[i]\).
  • Then do a Type \(2\) swap between strings \(a_0\) and \(a_x\) at column \(i\), swapping \(a_0[i]\) and \(a_x[i]\). Now \(a_0[i]=t[i]\).

By construction, we only touch columns \(\ge i\) of \(a_0\), so the fixed prefix \(a_0[0..i-1]\) is never broken, and the algorithm progresses monotonically.

Key WA pitfall (my mistake)
When searching in other strings for \(t[i]\), we must search the full range \(y\in[0,m-1]\), not just \(y\in[i,m-1]\). The reason is that only the prefix of \(a_0\) is “locked”; the left part of other strings is still a valid resource pool and can be rearranged freely. Restricting the search to \([i,m-1]\) can incorrectly miss an available character and cause a wrong answer.

Complexity
In the worst case, for each \(i\) we may scan \(a_0[i..m-1]\) and then scan all other strings to find \(t[i]\), so the time is \(O!\left(m^2 + nm^2\right)\) in the most pessimistic bound, but it is typically fast enough under the intended constraints. The memory usage is \(O(nm)\) to store the strings and \(O(\text{ops})\) to store operations.

Accepted Code (C++17)

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define i128 __int128
#define ld long double
#define fir first
#define sec second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lowbit(x) (x&-x)
using namespace std;
const int MOD=998244353;
const int MOD1=1e9+7;
//char ibuf[1<<25],*p1=buf,*p2=buf;
mt19937 mrand(random_device{}());
int rnd(int x){ return mrand() % x;}
ll qpow(ll a,ll b){ll res=1;while(b){if(b&1)res=res*a%MOD;a=a*a%MOD,b>>=1;}return res;}
ll gcd(ll a,ll b){ return b?gcd(a,a%b):a;}
ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}
//C++ 17 -O2
//By MaZhaoze
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T;
    cin>>T;
    while(T--){
        int n,m;
        cin>>n>>m;

        string t;
        cin>>t;
        vector<string> a(n);
        for(int i=0;i<n;i++) cin>>a[i];
        vector<array<int,4>> cz;
        for(int i=0;i<m;i++){
            if(a[0][i]==t[i]) continue;
            int j=-1;
            for(int k=i;k<m;k++){
                if(a[0][k]==t[i]){
                    j=k;
                    break;
                }
            }
            if(j!=-1){
                cz.push_back({1, 1, i+1, j+1});
                swap(a[0][i], a[0][j]);
                continue;
            }
            int x=-1,y=-1;
            for(int p=1;p<n&&x==-1;p++){
                for(int k=0;k<m;k++){
                    if(a[p][k]==t[i]){
                        x=p;
                        y=k;
                        break;
                    }
                }
            }
            if(x!=-1){
                if(y!=i){
                    cz.push_back({1, x+1, i+1, y+1});
                    swap(a[x][i], a[x][y]);
                }
                cz.push_back({2, 1, x+1, i+1});
                swap(a[0][i], a[x][i]);
            }
        }
        cout<<cz.size()<<'\n';
        for(auto op:cz){
            if(op[0]==1) {
                cout<<"1 "<<op[1]<<" "<<op[2]<<' '<<op[3]<<'\n';
            }else {
                cout<<"2 "<<op[1]<<' '<<op[2]<<' '<<op[3]<< '\n';
            }
        }
    }
    return 0;
}

In the end

B2B2C1059EA6CCCA5D2E415CE072294F

posted @ 2026-02-25 00:20  MagnusSM2  阅读(54)  评论(0)    收藏  举报