Codeforces Round #701 (Div. 2)赛后补题报告(A~D)
Codeforces Round #701 (Div. 2)賽后補題報告(A~D)
A. Add and Divide
原題信息
http://codeforces.com/contest/1485/problem/A
解題思路
對于題目基本有兩種方式,一種是直接暴力求解,第二種是使用函數求導進行嚴格證明
暴力求解
a=1e9a=1e^9a=1e9不難看出,操作最多為 50次,因為249=5629499534213122 ^ 49 = 562949953421312249=562949953421312 直接就超了
那么我們的 bbb最多也就是加50次,然后進行向下整除的模擬即可
一定要注意 b=0b = 0b=0這種情況。
函數求導
首先我們設操作次數為yyy,進行 b+=1b += 1b+=1的次數為xxx,可以得到的關系式為
y=x+(logb+xa+1)y = x + (log_{b+x}a+1)y=x+(logb+x?a+1),其中logb+xalog_{b+x}alogb+x?a是整除到1的次數,最后 +1是讓其變為0
下面我們對他進行求導
y′=1?lna(lnt)2?ty'=1-\frac{ln{a}}{(lnt)^2\cdot t}y′=1?(lnt)2?tlna?,其中t=b+x,t≥2并且t≥bt=b+x,t\geq2 并且 t\geq bt=b+x,t≥2并且t≥b
查看導函數的零點
(lnt)2?t=lna,t≥2并且t≥b{(lnt)^2\cdot t}=lna,t\geq2 并且 t\geq b(lnt)2?t=lna,t≥2并且t≥b,等式左側遞增,右側為常數lnalnalna,即至多有一個零點
倘若有一個零點
可以直接二分求得零點,我們在零點,零點+1, 零點-1進行求解得結果。
倘若沒有零點
直接就是t≥2并且t≥bt\geq2 并且 t\geq bt≥2并且t≥b取得最小值。
AC代碼
首先必須吐嘲一下,暴力沒往這個向限制,求導生疏了,整了半天,真雞兒狗
暴力枚舉代碼
函數求導代碼
#include <bits/stdc++.h> using namespace std;const int N = 100010; typedef long long LL; const double esp = 1e-5; LL a, b;int RealDo(LL a, LL b) {int ret = 0;while (a){ret ++;a /= b;}return ret; }int Get(LL a, LL b, LL tarb) {if (tarb <= 1 || tarb < b) return 0x3f3f3f3f;// return (tarb - b) + floor(log(a) / log(tarb)) + 1;return (tarb - b) + RealDo(a, tarb); }double Cal(LL a, LL b) {double lga = log(a);double l = b, r = 2e9, mid = b;if (lga <= mid * (log(mid) * log(mid)) ) // 不用加return mid;while (abs(l - r) >= esp){mid = (l + r) / 2;if (lga <= mid * (log(mid) * log(mid))) // 高了r = mid;else // 低了l = mid;}return mid; }int sol(LL a, LL b) {double x = Cal(a, b);return min(Get(a, b, x), min(Get(a, b, x + 1), Get(a, b, x - 1))); }int main() {int t;cin >> t;while (t -- ){scanf("%lld%lld", &a, &b);cout << sol(a, b) << endl;}return 0; }B. Replace and Keep Sorted
原題信息
http://codeforces.com/contest/1485/problem/B
解題思路
我們單獨考慮端點的可能性,已經中間結點不同的次數(可以使用前綴和)
但是一定要仔細考慮什么時候 + 1,什么時候沒有+1, 端點是否包括
AC代碼
#include <bits/stdc++.h> using namespace std;const int N = 100010; int n, k, q; int a[N]; int b[N];int cal(int l, int r) {if (l == r) return k - 1;else{int ret = (a[l] - 1) + (a[l + 1] - a[l] - 1) + (k - a[r]) + (a[r] - a[r - 1] - 1);if (l == r - 1)return ret;elsereturn ret + b[r - 1] - b[l]; // l + 1 ~ r - 1} } int main() {cin >> n >> q >> k;for (int i = 1; i <= n; i ++ )scanf("%d", &a[i]);memset(b, 0, sizeof b);for (int i = 2; i <= n - 1; i ++ )b[i] = (a[i] - a[i - 1] - 1) + (a[i + 1] - a[i] - 1);for (int i = 2; i <= n - 1; i ++ )b[i] += b[i - 1];while (q -- ){static int l, r;scanf("%d%d", &l, &r);// cout << "res" << endl << "\t";cout << cal(l, r) << endl;}return 0; }C. Floor and Mod
原題信息
http://codeforces.com/contest/1485/problem/C
解題思路
C題吐槽一下,當時復雜度分析錯了,O(N)O(\sqrt N)O(N?)分析成O(N)O(N)O(N),太絕了
設?ab?=a%b=t,t<b\lfloor\frac a b\rfloor=a\%b=t, t< b?ba??=a%b=t,t<b
那么a=t?b+t=(b+1)?t,A≥a≥1,B≥b≥1a=t \cdot b + t=(b+1)\cdot t, A\geq a\geq1,B\geq b\geq1a=t?b+t=(b+1)?t,A≥a≥1,B≥b≥1
- 當t=1t=1t=1時,a=b+1,b∈[2,B]a=b+1,b\in [2, B]a=b+1,b∈[2,B]
- 當t=2t=2t=2時,a=2?(b+1),b∈[3,B]a=2\cdot(b+1),b\in [3, B]a=2?(b+1),b∈[3,B]
- …
- 當t=it=it=i時,a=i?(b+1),b∈[i+1,B]a=i\cdot(b+1),b\in [i + 1, B]a=i?(b+1),b∈[i+1,B]
此時,i?(b+1)≤A,b≤B,b≥i+1i \cdot (b + 1)\leq A, b\leq B, b\geq i+1i?(b+1)≤A,b≤B,b≥i+1
?b∈[i+1,min(B,?Ai??1)]\Longrightarrow b\in [i + 1, min(B,\lfloor \frac A i \rfloor-1)]?b∈[i+1,min(B,?iA???1)]
如果?Ai??1\lfloor \frac A i \rfloor-1?iA???1有前綴和公式的話,是可以進行化簡為O(1)O(1)O(1)的
最后,b∈[i+1,min(B,?Ai??1)]b\in [i + 1, min(B,\lfloor \frac A i \rfloor-1)]b∈[i+1,min(B,?iA???1)]可以看出來iii的最大值,是無法取到1e91e91e9的,需要開個根號。
AC代碼
#include <bits/stdc++.h> using namespace std;typedef long long LL;void Sol(LL A, LL B) {LL a, b, tmp, ret = 0;for (int i = 1; true; i ++ ){tmp = min(B, A / i - 1);// i + 1 ~ tmpif (i + 1 > tmp) break;else ret += (tmp - (i + 1) + 1);}cout << ret << endl; }int main() {int t; cin >> t;while (t -- ){static LL a, b;scanf("%lld%lld", &a, &b);Sol(a, b);}return 0; }D. Multiples and Power Differences
原題信息
http://codeforces.com/contest/1485/problem/D
解題思路
可惡啊,這個題目是一個LCM的板子題,沒看出來。。。
首先,我們對1~16求LCM = x,我們的 B 數組首先全是x,可以滿足multiplemultiplemultiple的性質,然后我們湊性質三,發現可以直接進行隔項加上ai,j4a_{i, j}^4ai,j4?,而且數據范圍小,滿足性質1
AC代碼
#include <bits/stdc++.h> using namespace std;typedef long long LL; const int N = 510; int n, m; int a[N][N]; int b[N][N];int gcd(int x, int y) {if (y == 0) return x;else return gcd(y, x % y); }int lcm(int x, int y) {return LL(x) * y / gcd(x, y); }int main() {cin >> n >> m;for (int i = 1; i <= n; i ++ )for (int j = 1; j <= m; j ++ )scanf("%d", &a[i][j]);int x = 1;for (int i = 1; i <= 16; i ++ ){x = lcm(x, i);}for (int i = 1; i <= n; i ++ )for (int j = 1; j <= m; j ++ )b[i][j] = x;for (int i = 1; i <= n; i ++ ){for (int j = (i % 2 == 1 ? 1 : 2); j <= m; j += 2){b[i][j] += (a[i][j] * a[i][j]) * (a[i][j] * a[i][j]);}}// outputfor (int i = 1; i <= n; i ++ ){printf("%d", b[i][1]);for (int j = 2; j <= m; j ++ )printf(" %d", b[i][j]);puts("");}return 0; }總結
- 首先考慮暴力,能否直接縮小范圍,省時間
- 其次,考慮復雜度的時候,分析準確一些
- 多考慮邊界的情況,+1,-1
- 最后題型要把握清楚,數據范圍小的時候,有時候會暴力,有時候直接lcm。。。
總結
以上是生活随笔為你收集整理的Codeforces Round #701 (Div. 2)赛后补题报告(A~D)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flink的Table API 与SQL
- 下一篇: java中字母用什么单词赋值_Java初