D: Defuse the Bombs
有n个计数器,初值为$a_i$,每秒钟可以将一个计数器的值+1,然后所有的计数器的值-1。问最多几秒后所有计数器的最小值$\lt 0$$n\leq 10^5, 0 \leq a_i \leq 10^9$
做法
转化一下问题:每秒钟可以让一个计数器值+1,第i秒钟要求所有计数器的值$\geq i$,问第几秒后不满足。假如第x秒钟满足条件,则要满足$sum_p+x \geq x*p$,其中$a_p$为小于x的最大的p。先枚举$a_i$,找到第一个不满足的,那么答案就是$\frac{sum_i}{i-1}+1$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <bits/stdc++.h> using namespace std; using ll = long long; const int N = 1e5 + 5; int n, a[N]; ll sum[N]; void solve(int kase) { cin >> n; for(int i=1; i<=n; i++) cin >> a[i]; sort(a+1, a+n+1); for(int i=1; i<=n; i++) sum[i] = sum[i-1] + a[i]; cout << "Case #" << kase << ": "; ll p = 0; for(int i=1; i<=n; i++) { if(1ll*i*a[i]-sum[i]>a[i]) break; p = i; } cout << sum[p]/(p-1)+1 << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _; cin >> _; for(int kase=1; kase<=_; kase++) solve(kase); return 0; }
|
K Knowledge is Power
给定数x,要求将其分解成若干大于1的数,要求满足两两互质且和为x。最小化这些数的最大值和最小值的差值。$5 \leq x \leq 10^9$
做法
x为奇数,显然$2\frac{x-1}{2}, \frac{x+1}{2}$最优,为1考虑x为偶数:x=6无解x=8,分成3和5即可(我一开始误判成无解)通过打表得到答案只可能是2,3,4x是3的倍数,显然可以分成y, y+1, y+2的形式,又由于y一定是奇数,所以合法,答案为2$x%3==1$,如果能分成互质的y, y+1, y+3则为3,否则为4$x%3==2$,如果能分成互质的y, y+2, y+3则为3,否则为4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <bits/stdc++.h> using namespace std; void solve(int kase) { int x; cin >> x; cout << "Case #" << kase << ": "; if(x==6) cout << -1 << '\n'; else if(x&1) cout << 1 << '\n'; else { if(x%3==0) cout << 2 << '\n'; else if(__gcd(x/2-1, x/2+1)==1) cout << 2 << '\n'; else { bool ok = 0; if(x%3==2) { int a = (x-5)/3, b = a+2, c = a+3; if(__gcd(a, b)==1 && __gcd(a, c)==1 && __gcd(b, c)==1) ok = 1; } if(x%3==1) { int a = (x-4)/3, b = a+1, c = a+3; if( __gcd(a, b)==1 && __gcd(a, c)==1 && __gcd(b, c)==1) ok = 1; } if(ok) cout << 3 << '\n'; else cout << 4 << '\n'; } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _; cin >> _; for(int k=1; k<=_; k++) solve(k); return 0; }
|
J Joy of Handcraft
有n个灯泡,分别有周期$t_i$,每两个周期中,前一个周期亮,后一个周期暗,有亮度$x_i$。问1-m每个时间内的最大亮度$n \leq 10^5, m \leq 10^5, t_i \leq 10^5, x_i \leq 10^5$
做法
周期相同的只要取亮度最大的那个,然后暴力枚举每种周期的灯泡亮的时间,复杂度是$O(n\log n)$,注意到将亮度排序后,就是个区间覆盖问题了,线段树即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; int n, m; int cov[N<<2]; void push(int p) { cov[p<<1] = cov[p<<1|1] = cov[p]; cov[p] = 0; } void cover(int p, int l, int r, int x, int y, int v) { if(l>=x && r<=y) { cov[p] = v; return; } if(cov[p]) push(p); int mid = (l+r)>>1; if(x<=mid) cover(p<<1, l, mid, x, y, v); if(y>mid) cover(p<<1|1, mid+1, r, x, y, v); } void print(int p, int l, int r) { if(l==r) { cout << cov[p] << " \n"[l==m]; return; } if(cov[p]) push(p); int mid = (l+r)>>1; print(p<<1, l, mid); print(p<<1|1, mid+1, r); } void solve(int kase) { cin >> n >> m; for(int i=1; i<=4*m; i++) cov[i] = 0; vector<pair<int, int>> lamb(n); for(auto &it : lamb) cin >> it.first >> it.second; sort(begin(lamb), end(lamb)); vector<pair<int, int>> tmp; for(int i=0; i<(int)lamb.size(); ) { int j = i + 1; while(j<(int)lamb.size() && lamb[j].first==lamb[i].first) ++j; tmp.push_back({lamb[j-1].second, lamb[j-1].first}); i = j; } sort(begin(tmp), end(tmp)); for(auto it : tmp) for(int k=1; k<=m; k+=2*it.second) cover(1, 1, m, k, min(m, k+it.second-1), it.first); cout << "Case #" << kase << ": "; print(1, 1, m); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _; cin >> _; for(int k=1; k<=_; k++) solve(k); return 0; }
|
L Lottery
有n种石头,第i种石头体积为$2^{a_i}$,数量为$x_i$,问能拼成的体积数量。$n \leq 10^5, a_i, x_i \leq 10^9$
做法
按照体积从小到大考虑设当前枚举到第i块石头,前$i-1$块石头(前mx的体积中)不能拼成的体积为ans,前$2^{a_{i-1}}$的体积中有delta个不能被拼成,之前所有石头能拼成的最大体积为$mx$。$mx\geq 2^{a_i}$:那么对于$2^{a_{i-1}}$到$2^{a_i}$之间,每$2^{a_{i-1}}$个就有delta个体积不能被拼成。因此$\leq 2^{a_i}$的体积中不能拼成的体积的数量就是$2^{a_i-a_{i-1}}\times delta$,前i块石头不能拼成的体积就要增加$delta\times x_i$个$mx\lt 2^{a_i}$:那么$mx+1$到$2^{a_i}-1$之间的体积就无法拼成前$2^{a_{i}}$的体积中有$ans+2^{a_i}-mx-1$不能被拼成前i块石头不能拼成的体积增加$delta\times x_i$个
由于有取模操作,不能直接判断$mx$和$2^{a_i}$的大小关系,用一个map来存储mx的二进制表示即可,只要mx的二进制中最高位high$\geq a_i$,就说明$mx \geq 2^{a_i}$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <bits/stdc++.h> #define fi first #define se second using namespace std; const int N = 1e5 + 5, mod = 1e9 + 7; int n; pair<int, int> p[N]; int Pow(int a, int b) { int ans = 1; while(b) { if(b&1) ans = 1ll*ans*a%mod; a = 1ll*a*a%mod; b >>= 1; } return ans; } void solve(int kase) { cin >> n; for(int i=1; i<=n; i++) cin >> p[i].fi >> p[i].se; map<int, int> bit; sort(p+1, p+n+1); int mx = 0, delta = 0, ans = 0, high = -1; for(int i=1; i<=n; i++) { int cur = Pow(2, p[i].fi); if(high>=p[i].fi) { delta = 1ll*delta*Pow(2, p[i].fi-p[i-1].fi)%mod; } else { delta = ((cur-mx-1+ans)%mod+mod)%mod; } ans = (ans + 1ll*delta*p[i].se)%mod; mx = (mx + 1ll*cur*p[i].se)%mod; for(int j=0; j<30; j++) if((p[i].se>>j)&1) { int x = p[i].fi + j; bit[x]++; while(bit[x]==2) { bit[x] = 0; ++x; bit[x]++; } high = max(high, x); } } cout << "Case #" << kase << ": "; cout << ((mx - ans + 1)%mod+mod)%mod << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _; cin >> _; for(int k=1; k<=_; k++) solve(k); return 0; }
|
G Game of Cards
有$c_0$个0号牌,$c_1$个1号牌,$c_2$个2号牌,$c_3$个3号牌,每次操作可以选取两张和不超过3的牌,然后将这两张牌换成一张它们的和的号的牌,不能操作者输。$0\leq c_0,c_1,c_2, c_3\leq 10^9$
做法
简单分析一下:3号牌只能和0号牌组合,且只会增加不会减少,影响到局面的就是3号牌有还是没有。如果操作0号牌,每次必然会减少1,所以0号牌影响局面的是它的奇偶性。然后只需要对1和2的数目以及3号牌是0还是1,0号牌是奇数还是偶数打个sg表即可。发现只有0号牌时,需要特判。此外3号牌没有影响。0号牌有偶数个时,2号牌为0和非0时,1号牌模3各有一个规律0号牌有奇数个时,2号牌为0和1和>1时,1号牌模3各有一规律if else一下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include <bits/stdc++.h> using namespace std; void win() { cout << "Rabbit\n"; } void lose() { cout << "Horse\n"; } void solve(int kase) { int a, b, c, d; cin >> a >> b >> c >> d; cout << "Case #" << kase << ": "; bool ok = 0; if(a%2==0) { if(!c) { if(b%3==2) ok = 1; else ok = 0; } else { if(b%3==0) ok = 0; else ok = 1; } } else { if(!c) { if(b%3==2) ok = 0; else ok = 1; } else if(c==1) { if(b%3==0) ok = 1; else ok = 0; } else { if(b%3==1) ok = 0; else ok = 1; } } if(!b&&!c&&!d) { if(a<=1) ok = 0; else if(a&1) ok = 0; else ok = 1; } ok ? win() : lose(); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _; cin >> _; for(int k=1; k<=_; k++) solve(k); return 0; }
|