Codeforces Round #526 (Div. 2) E. The Fair Nut and Strings
阿新 • • 發佈:2018-12-14
and open contest blank onclick 分享 兩個 多少 int
E. The Fair Nut and Strings
題目鏈接:https://codeforces.com/contest/1084/problem/E
題意:
輸入n,k,k代表一共有長度為n的多少個字符串。然後給出一個最小字符串s,最大字符串t,滿足對於所有的k個字符串有s<=S<=t。
最後求滿足條件的k個字符串(自己構造)的不同前綴數量的和。
題解:
這題很巧妙,設dp(i)表示長度為i的前綴的數量和,一開始有dp(1)=0。
後來隨著長度的增加,我們每次可以在最後加一個a或者b,所以轉移方程為dp(i)=2*dp(i-1)。
但是由於有最大最小字符串的限制,當si=b時,dp(i)會多加一個;當ti=a時,dp(i)也會多加一個。減去即可。
可以用歸納法來證明,假設當前循環到第i層,前綴長度i-1滿足限制條件。那麽si=b時,dp(i-1)中,只有一個後面加上a時,會小於s;對於ti=a也同理。(可以想一下,提示:共同前綴)
最後輸出求和min(dp(i),k)。(k個字符串任意長度的前綴最多也只有k個)
註意一下代碼的細節。
代碼如下:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 5e5+5; ll n,k; char s[N],t[N]; ll dp[N];View Codeint main(){ cin>>n>>k; scanf("%s%s",s,t); dp[0]=1; ll ans = 0; for(int i=1;i<=n;i++){ char sc = s[i-1],tc = t[i-1]; dp[i]=2ll*dp[i-1]; if(sc==‘b‘) dp[i]--; if(tc==‘a‘) dp[i]--; if(dp[i]>=k){ dp[i]=k; ans+=(n-i)*k; break ; } } for(int i=1;i<=n;i++) if(dp[i]) ans+=dp[i]; printf("%I64d",ans); return 0; }
還有一種就是把字符串看為二進制的,那麽數量就為兩個二進制相減。
直接給代碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e6 ; char s[N],t[N]; ll n,k; int main(){ cin>>n>>k; scanf("%s %s",s,t); ll a=0,b=0; ll ans =0; for(int i=0;i<n;i++){ ll now; a<<=1;b<<=1; if(s[i]==‘b‘) a++; if(t[i]==‘b‘) b++; now = b-a+1; if(now>=k){ ans+=(n-i)*k; break ; } ans+=now; } printf("%I64d",ans); return 0; }View Code
Codeforces Round #526 (Div. 2) E. The Fair Nut and Strings