1829G Hits Different
The problem can be found here
My Thought Process
Well, what happens when one of the cans is hit on row $x$. The cans to the left and to the right of it on row $x-1$ are also hit.
If the starting can is on row $x$, on the $y$th can on the left, then the $y-1$th and $y$th cans will also be hit (if they exist) and so on. Essentially we can iterate from bottom to top keeping track of an interval of $[l,r]$ cans and keep subtracting $l$ by one until it reaches $1$ and also adjusting $r$ so we are not out of range.
We then essentially have our algorithm. First of all, we can precompute prefix sums of the rows.
Then, we can figure out the row of the starting can and $l$ and $r$ from there by subtracting $n$ from the number of cans in previous rows. See the implementation for more details
Implementation
#include <bits/stdc++.h>
using ll = long long;
#define pb push_back
using namespace std;
const int MOD = 1e9+7;
const int MAXN = 2e6+1;
const int INF = 2e9;
const long long IINF = 2e18;
#define int long long
vector<vector<int>> pfs(2024);
void solve() {
int n;
cin >> n;
int x = 0;
int c = 0;
while(x < n){
x += (c + 1);
c++;
}
int l = n - (c * (c - 1)/2);
int r = n - (c * (c - 1)/2);
int ans = 0;
for(int row = c; row >= 1; --row){
ans += pfs[row][r] - pfs[row][l-1];
l = max(1LL, l - 1);
r = min(r, row - 1);
}
cout << ans << endl;
}
int32_t main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
int c = 1;
for(int i = 1; i <= 2023; ++i){
pfs[i].pb(0);
for(int j = 1; j <= i; ++j){
pfs[i].pb(pfs[i].back() + c * c);
c++;
}
}
int t;
cin >> t;
while(t--){
solve();
}
return 0;
}
See here for the solution and another implementation.