Codeforces Round #506 (Div. 3)ABCDEF

並無參加比賽,全是賽後AC

A題

  題意:現有一個長度爲n的字符串s。你須要構建一個長度最小的字符串t,使得t中剛好包含k個s(容許部分重疊),輸出這個字符串

 

  

 1 /*
 2     咱們能夠很是容易的發現咱們構造出來的字符串t有着鮮明的特徵。即t中有大量重複的子串,能夠證實的是t = S + (K-1)*A, A是S串中刪去一段字符串(這段字符串知足既是S的前綴又是S的後綴)。
 3 */
 4 #include<cstdio>
 5 #include<iostream>
 6 
 7 using namespace std;
 8 
 9 const int maxn = 50 + 5;
10 
11 char a[maxn];
12 int n, k;
13 
14 int main(void) {
15     scanf("%d%d", &n, &k);
16     scanf("%s", a + 1);
17     string s1 = "", s2 = ""; int res = 0;
18     for (int i = 1, j = n; i < n; ++ i, -- j) {
19         s1 = s1 + a[i];
20         s2 = a[j] + s2;
21         if (s1 == s2) res = max(res, i);
22     }
23     int len = n - res; 
24 //    cout << len << endl;
25     string ans = "";
26     for (int i = n; i >= n - len + 1; -- i) ans = a[i] + ans;
27     for (int i = 1; i <= n; ++ i) printf("%c", a[i]);
28     for (int i = 1; i < k; ++ i) cout << ans; puts("");
29     return 0;
30 }

 

B題

  題意:給出一個長度爲n的數組A,數組A中的元素a[i]知足(1<=a[i]<=10^9),且a[i]嚴格大於a[i-1](2<=i<=n)。如今要你找出一個數組B,知足數組B中全部元素在A中都是有序排列的,即B是A的非連續子序列,數組B中的元素要知足b[i]>=2*b[i-1],輸出這個數組B的最大長度。

 1 /*
 2 一個相似導彈攔截的DP+決策單調性優化(這個優化由單調隊列實現)
 3 */
 4 #include<cstdio>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 
 9 const int maxn = 2e5 + 5;
10 
11 int n, a[maxn], f[maxn], Stack[maxn], val[maxn];
12 
13 
14 int main(void) {
15     scanf("%d", &n);
16     for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
17     int L = 1, R = 1;
18     Stack[1] = 1;
19     val[1] = 1;
20     int ans = 1;
21     // a值小f值大 和 a值大f值小 
22     for (int i = 2; i <= n; ++ i) {
23         while (L <= R && a[Stack[L]] * 2 < a[i]) ++ L;
24         if (L <= R) {
25             int cur = val[L] + 1;
26             ans = max(ans, cur);
27             while (L <= R && cur >= val[R]) -- R;
28             ++ R; Stack[R] = i; val[R] = cur;        
29         } else {
30             int cur = 1;
31             ++ R; Stack[R] = i; val[R] = cur;
32         }
33     }
34     printf("%d\n", ans);
35     return 0;
36 }

 

C題:

  題意:給出n個區間(2<=n<=3e5),區間的左右邊界均在[0,1e9]之間,現要你去掉一個區間,求出剩下n-1個區間的區間交,使得這個區間交的長度最大。輸出這個長度

 

 1 /*
 2     咱們維護兩個東西,一個是區間並的前綴f[i],另外一個是區間並的後綴g[i]。若是咱們去掉i這個區間,答案就是f[i-1]這個區間和g[i+1]這個區間的區間並。
 3     
 4 */
 5 #include<bits/stdc++.h>
 6 
 7 using namespace std;
 8 
 9 const int maxn = 3e5 + 5;
10 
11 int n, l[maxn], r[maxn];
12 
13 struct node {
14     int l, r;
15 } f[maxn], g[maxn];
16 
17 pair<int, int> Make(int l0, int r0, int l1, int r1) {
18     if (l0 > l1) {
19         swap(l0, l1); swap(r0, r1);
20     }
21     // [l0, r0] [l1, r1]  l0 <= l1
22     if (r0 <= l1) return make_pair(-1, -1);
23     if (r0 >= r1) return make_pair(l1, r1);
24     return make_pair(l1, r0);
25 } // 輸入兩個區間,返回他們的並區間
26 
27 int Get_Ans(pair<int, int> tmp) {
28     return tmp.second - tmp.first;
29 } //獲得區間tmp的長度。
30 
31 int main(void) {
32     scanf("%d", &n);
33     for (int i = 1; i <= n; ++ i) scanf("%d%d", &l[i], &r[i]);
34     
35     int L = l[1], R = r[1];
36     f[1].l = L; f[1].r = R;
37     for (int i = 2; i <= n; ++ i) {
38         pair<int, int> tmp = Make(L, R, l[i], r[i]);
39         L = f[i].l = tmp.first;    R = f[i].r = tmp.second;
40     }
41     
42     L = l[n]; R = r[n];
43     g[n].l = L; g[n].r = R;
44     for (int i = n - 1; i >= 1; -- i) {
45         pair<int, int> tmp = Make(L, R, l[i], r[i]);
46         L = g[i].l = tmp.first; R = g[i].r = tmp.second;
47     }
48     
49     int ans = max(Get_Ans(make_pair(g[2].l, g[2].r)), Get_Ans(make_pair(f[n - 1].l, f[n - 1].r)));
50     
51     for (int i = 2; i < n; ++ i) {
52         ans = max(ans, Get_Ans(Make(f[i - 1].l, f[i - 1].r, g[i + 1].l, g[i + 1].r)));
53     }
54     printf("%d\n", ans);
55     return 0;
56 }

 

D題:

  題意:給出一個長度爲n的數組A和一個k,知足1<=n<= 2e5, 2<=k<=1e9,1<=a[i]<=1e9。如今你能夠拿出A數組裏面的兩個數字a[i]和a[j](i!=j),將a[i]和a[j]拼在一塊兒造成一個大數(例如5和123拼在一塊兒能夠拼出5123)若是這個拼成的大數是k的倍數,那麼++ Ans。要求輸出Ans。

  我好菜啊:

 

 1 /*
 2 這題我。。。唉。(由於某個智障錯誤個人代碼比別人的代碼慢了20%,T了11發才發現。。)
 3 思路:咱們考慮鏈接好的大數x,能夠發現x%k==0這個條件等價於把x減去好多好多的k,直到把x減到0爲止。因而乎,咱們就發現了一個算法,就是咱們把a[i]*(10^(a[j]的長度))對K取模,獲得一個小於k的數字x2,
 4 而後在把a[j]對k取模,獲得一個小於k的數字y2。那麼(x2+y2)%k等價於原來的大數%k。咱們這麼處理後就能夠用map來維護這個東西。計算答案就簡單啦。
 5     智障錯誤是:我計算i的時候爲了防止a[i]和a[i]拼在一塊兒的狀況出現,直接在map裏面消除了a[i]的影響,算完後再加上去,這個操做複雜度是log的還帶上一個巨大的常數,結果就T了幾百ms,別人算法的這個操做都是O(1)的。。。。我好菜啊
 6 */
 7 #pragma GCC diagnostic error "-std=c++11"
 8 #pragma GCC target("avx")
 9 #pragma GCC optimize(3)
10 #pragma GCC optimize("Ofast")
11 #pragma GCC optimize("inline")
12 #pragma GCC optimize("-fgcse")
13 #pragma GCC optimize("-fgcse-lm")
14 #pragma GCC optimize("-fipa-sra")
15 #pragma GCC optimize("-ftree-pre")
16 #pragma GCC optimize("-ftree-vrp")
17 #pragma GCC optimize("-fpeephole2")
18 #pragma GCC optimize("-ffast-math")
19 #pragma GCC optimize("-fsched-spec")
20 #pragma GCC optimize("unroll-loops")
21 #pragma GCC optimize("-falign-jumps")
22 #pragma GCC optimize("-falign-loops")
23 #pragma GCC optimize("-falign-labels")
24 #pragma GCC optimize("-fdevirtualize")
25 #pragma GCC optimize("-fcaller-saves")
26 #pragma GCC optimize("-fcrossjumping")
27 #pragma GCC optimize("-fthread-jumps")
28 #pragma GCC optimize("-funroll-loops")
29 #pragma GCC optimize("-fwhole-program")
30 #pragma GCC optimize("-freorder-blocks")
31 #pragma GCC optimize("-fschedule-insns")
32 #pragma GCC optimize("inline-functions")
33 #pragma GCC optimize("-ftree-tail-merge")
34 #pragma GCC optimize("-fschedule-insns2")
35 #pragma GCC optimize("-fstrict-aliasing")
36 #pragma GCC optimize("-fstrict-overflow")
37 #pragma GCC optimize("-falign-functions")
38 #pragma GCC optimize("-fcse-skip-blocks")
39 #pragma GCC optimize("-fcse-follow-jumps")
40 #pragma GCC optimize("-fsched-interblock")
41 #pragma GCC optimize("-fpartial-inlining")
42 #pragma GCC optimize("no-stack-protector")
43 #pragma GCC optimize("-freorder-functions")
44 #pragma GCC optimize("-findirect-inlining")
45 #pragma GCC optimize("-fhoist-adjacent-loads")
46 #pragma GCC optimize("-frerun-cse-after-loop")
47 #pragma GCC optimize("inline-small-functions")
48 #pragma GCC optimize("-finline-small-functions")
49 #pragma GCC optimize("-ftree-switch-conversion")
50 #pragma GCC optimize("-foptimize-sibling-calls")
51 #pragma GCC optimize("-fexpensive-optimizations")
52 #pragma GCC optimize("-funsafe-loop-optimizations")
53 #pragma GCC optimize("inline-functions-called-once")
54 #pragma GCC optimize("-fdelete-null-pointer-checks")
55 #include<iostream>
56 #include<cstdio>
57 #include<map>
58 #define ll long long
59 #define LG 32
60 #define N 200100
61 using namespace std;
62 
63 ll n,m,ten[40],num[N],ans;
64 map<ll,ll>cnt[40];
65 
66 inline ll ws(ll u){ll res=0;for(;u;u/=10) res++;return res;}
67 
68 int main()
69 {
70     ll i,j,p,q;
71     cin>>n>>m;
72     ten[0]=1;
73     for(i=1;i<=LG;i++) ten[i]=ten[i-1]*10%m;
74     for(i=1;i<=n;i++)
75     {
76         scanf("%lld",&num[i]);
77         cnt[ws(num[i])][num[i]%m]++;
78     }
79     for(i=1;i<=n;i++)
80     {
81         p=num[i];
82         for(j=1;j<=LG;j++)
83         {
84             p=p*10%m;
85             if(cnt[j].count((m-p)%m))
86                 ans+=cnt[j][(m-p)%m];
87         }
88         if((num[i]*ten[ws(num[i])]+num[i])%m==0) ans--;
89     }
90     cout<<ans;
91 }

 

E題:

  題意:給出一個節點數量爲n的樹,邊權都爲1,。而後定義dis[i]爲i號節點到1號節點的最短路徑的距離。而後有一個加邊的操做,你能夠隨意鏈接兩個點,邊權爲1。顯然這個加邊操做能夠顯著縮小某些點的dis值。現問你最少要加幾條邊纔可讓全部的點的dis值所有小於3。輸出這個加邊操做的最小數量。

 1 /*
 2 這題就是貪心啊,咱們能夠知道若是咱們對這顆樹(固然若干次操做後就不是一顆樹了)上加一條邊,那麼這條邊的一頭必定是1(由於這樣最優啊)。而後若是咱們設Mx爲當前最大的dis值,那麼這條邊鏈接的必定是一個dis值爲Mx - 1的節點(由於這樣最優啊)。因而咱們就獲得了一個貪心。寫得優美點就是下面的程序啦!
 3 */
 4 #pragma GCC optimize(3)
 5 #include<cstdio>
 6 #include<vector>
 7 
 8 using namespace std;
 9 
10 const int maxn = 2e5 + 5;
11 
12 int n, ans = 0;
13 vector<int> G[maxn];
14 
15 int dfs(int x, int fat) {
16     int dis = 2;
17     for (unsigned i = 0; i < G[x].size(); ++ i) {
18         int v = G[x][i]; if (v == fat) continue;
19         dis = min(dis, dfs(v, x));
20     }
21     if (dis == 0 && x != 1 && fat != 1) ++ ans;
22     return (dis + 1) % 3;
23 }
24 
25 int main(void) {
26     scanf("%d", &n);
27     for (int i = 1; i < n; ++ i) {
28         int x, y; scanf("%d%d", &x, &y);
29         G[x].push_back(y);
30         G[y].push_back(x);
31     }
32     dfs(1, 0);
33     printf("%d\n", ans);
34     return 0;
35 }

 

F題:

  題意:現有一面長寬可無線延伸的網格,現要求將aa個格子染成紅色,bb個格子染成藍色。要求染成的圖形爲矩形,且至少有一種顏色染成了矩形。求染成的圖形的最小周長。

 

 1 /*
 2 枚舉(a+b)大小的矩形的邊長,並暴力判斷(注意暴力判斷的順序)可否成立,更新答案。
 3 */
 4 #include <bits/stdc++.h>
 5 
 6 #define forn(i, n) for (int i = 0; i < int(n); i++)
 7 
 8 typedef long long li;
 9 
10 using namespace std;
11 
12 const int N = 1000 * 1000;
13 
14 int lens[N];
15 int k;
16 
17 li solve(li a, li b){
18     k = 0;
19     for (li i = 1; i * i <= b; ++i)
20         if (b % i == 0)
21             lens[k++] = i;
22     
23     li ans = 2 * (a + b) + 2;
24     li x = a + b;
25     int l = 0;
26     for (li i = 1; i * i <= x; ++i){
27         if (x % i == 0){
28             while (l + 1 < k && lens[l + 1] <= i)
29                 ++l;
30             if (b / lens[l] <= x / i)
31                 ans = min(ans, (i + x / i) * 2);
32         }
33     }
34     
35     return ans;
36 }
37 
38 int main() {
39     li a, b;
40     scanf("%lld%lld", &a, &b);
41     printf("%lld\n", min(solve(a, b), solve(b, a)));
42     return 0;
43 }
相關文章
相關標籤/搜索