Codeforces 1043 - A/B/C/D/E/F - (Undone)
連結:http://codeforces.com/contest/1043
A - Elections - [水水水水題]
題意:
我和另一個人競爭選舉,共有 $n$ 個人投票,每個人手上有 $k$ 票,必須投給我或者另一個人。
現在已知每個人給另一個人投 $a_i$ 票,也就是說會給我投 $k-a_i$ 票。求最小的整數 $k$,使得我的票數嚴格大於另一個人。
題解:
暴力列舉 $k$。
AC程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn=105; int n,a[maxn]; int main() { cin>>n; int mx=1,sum=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]), mx=max(a[i],mx), sum+=a[i]; for(int k=mx;;k++) { if(sum<n*k-sum) { printf("%d\n",k); break; } } }
B - Lost Array - [簡單數學題]
題意:
我手上有一個序列 $x_0,x_1, \cdots, x_{k-1}$。
現在又有一個長度為 $n+1$ 的序列 $a_0,a_1,a_2, \cdots, a_n$,已知這個序列是通過 $a_i = x_{(i-1) \mod k} + a_{i-1}$ 計算得到,其中 $i \ge 0$ 且 $a_0 = 0$。
現在序列 $x_0,x_1, \cdots, x_{k-1}$ 丟失了,但給你 $a_0,a_1,a_2, \cdots, a_n$,求可能的 $k(1 \le k \le n)$。
題解:
顯然從 $a_1$ 到 $a_k$ 是可以用來直接確定 $x_0,x_1, \cdots, x_{k-1}$,而後面的 $a_{k+1} \sim a_n$ 可以用來判定是否矛盾,不矛盾就是可行的 $k$。
AC程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn=1e3+10; int n,a[maxn]; int x[maxn]; inline bool ok(int k) { for(int i=1;i<=k;i++) x[i-1]=a[i]-a[i-1]; for(int i=k+1;i<=n;i++) { if(a[i]!=x[(i-1)%k]+a[i-1]) return 0; } return 1; } int main() { cin>>n; a[0]=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); vector<int> ans; for(int k=1;k<=n;k++) { if(ok(k)) ans.push_back(k); } printf("%d\n",ans.size()); for(int i=0;i<ans.size();i++) printf("%s%d",i>0?" ":"",ans[i]); }
C - Smallest Word - [簡單模擬]
題意:
給出只包含字元 $a,b$ 的字串 $s$,現在你從長度為 $1$ 到 $|s|$ 依次遍歷所有的字首子串,你可以選擇反轉這個字首子串,或者不動。
現在要你輸出 $|s|$ 個選擇,使得最後的 $s$ 字典序最小。
題解:
從左到右遍歷字串,對於第 $i$ 個字元,始終保持 $1 \sim i-1$ 個字元保持 "$a,a,\cdots,a,b,b,\cdots,b$" 或者 "$b,b,\cdots,b,a,a,\cdots,a$" 這樣的樣式。
可以使得最後字串為 "$a,a,\cdots,a,b,b,\cdots,b$"。
AC程式碼:
#include<bits/stdc++.h> using namespace std; string s; int main() { cin>>s; char pre=s[0]; for(int i=1;i<s.size();i++) { if(s[i]=='a') { if(pre=='b') printf("1 "), pre='a'; else printf("0 "); } if(s[i]=='b') { if(pre=='a') printf("1 "), pre='b'; else printf("0 "); } } if(pre=='a') printf("1\n"); else printf("0\n"); }
D - Mysterious Crime - [雙指標維護]
題意:
給出 $m$ 個 $1 \sim n$ 的排列,求所有公共子串的數目。
題解:
換句話說,就是在第 $1$ 個排列裡找,在其他 $2 \sim m$ 個排列裡出現的所有公共子串。
不難想到,可以將第 $1$ 個排列分成若干段,每段都是不能在往右延伸的最長公共子串,例如:$(1,2,3,6,4,5)$ 和 $(4,5,6,1,2,3)$,則可以把第 $1$ 個排列分成 $(1,2,3),(6),(4,5)$。
因此用兩根指標分別維護這些段的左右端點,每次找到一個長為 $len$ 的段,就產生貢獻 $\frac{(len)(len+1)}{2}$。
AC程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+10; const int maxm=15; int n,m; int nxt[maxm][maxn]; int main() { cin>>n>>m; memset(nxt,0,sizeof(nxt)); for(int j=1;j<=m;j++) { for(int i=1,now,pre=0;i<=n;i++) { scanf("%d",&now); nxt[j][pre]=now; pre=now; } } ll ans=0; int len=1; for(int i=nxt[1][0],j;i;i=nxt[1][i]) { for(j=2;j<=m;j++) { if(nxt[j][i]!=nxt[1][i]) break; } if(j>m && nxt[1][i]) len++; else ans+=(ll)len*(len+1)/2, len=1; } cout<<ans<<endl; }
E - Train Hard, Win Easy - (Undone)
F - Make It One - (Undone)