AtCoder Beginner Contest 155 題解
阿新 • • 發佈:2021-07-02
傳送門:這裡
這場好難,枯了。
A
分類討論
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[3];
for(int i=0; i<3; i++) cin>>a[i];
sort(a, a+3);
if(a[0]==a[1] && a[1]!=a[2] || a[0]!=a[1] && a[1]==a[2]) puts("Yes");
else puts("No");
return 0;
}
B
模擬
#include<bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; bool ok=true; while(n--){ int t; cin>>t; if(t%2==0){ if(t%3!=0 && t%5!=0) ok=false; } } puts(ok? "APPROVED": "DENIED"); return 0; }
C
模擬
#include<bits/stdc++.h> using namespace std; map<string, int> mp; int main(){ int n; cin>>n; while(n--){ string t; cin>>t; mp[t]++; } int num=0; for(auto i: mp) num=max(num, i.second); for(auto i: mp) if(i.second==num) cout<<i.first<<endl; return 0; }
D
二分答案,看看二分出來的 \(v\) 在所有數中的排名。麻煩在於求排名的時候也要二分 qwq
#pragma GCC optimize("O3") #include<bits/stdc++.h> using namespace std; #define endl '\n' #define debug(x) cerr << #x << ": " << x << endl #define pb(a) push_back(a) #define set0(a) memset(a,0,sizeof(a)) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define dwn(i,a,b) for(int i=(a);i>=(b);i--) #define ceil(a,b) (a+(b-1))/b #define INF 0x3f3f3f3f #define ll_INF 0x7f7f7f7f7f7f7f7f typedef long long ll; typedef pair<int,int> PII; typedef pair<double,double> PDD; #define int long long inline void read(int &x) { int s=0;x=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')x=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar(); x*=s; } const int N=2e5+5; int n, k; int w[N]; int get_rank(int v){ int rk=0; rep(i,1,n-1){ int cur=w[i]; if(cur<0){ int L=i+1, R=n; while(L<R){ int mid=L+R>>1; if(v>cur*w[mid]) R=mid; else L=mid+1; } if(v>cur*w[L]) rk+=n-L+1; } else{ int L=i+1, R=n; while(L<R){ int mid=L+R+1>>1; if(v>cur*w[mid]) L=mid; else R=mid-1; } if(v>cur*w[L]) rk+=L-i; } } rk++; // debug(rk); return rk; } signed main(){ read(n), read(k); rep(i,1,n) read(w[i]); sort(w+1, w+1+n); int l=-1e18, r=1e18; while(l<r){ int mid=l+r+1>>1; if(get_rank(mid)<=k) l=mid; else r=mid-1; } cout<<l<<endl; return 0; }
E
分析
我們採取 dp 的做法。
為了直觀地考慮這個問題,我們將原串用 \(a\) 表示,根據題意,我們的目標是最小化 \(\sum (b_i+c_i)\) (求最小代價)。
\(\begin {array}{ccc} &a_n&a_{n-1}&...&a_1\\ +&b_n&b_{n-1}&...&b_1\\ \hline =&c_n&c_{n-1}&...&c_1 \end {array}\)
不失一般性,考察第 \(i\) 位,分成兩種情況討論:
-
第 \(i\) 位發生進位。
-
第 \(i\) 位不發生進位。
對於第一種情況:
我們有 \(a_i + b_i = 10 + c_i\) (因為發生了進位),要最小化 \(b_i + c_i\) ,
因為 \(b_i + c_i = 2b_i + a_i - 10\) ,我們只需要最小化 \(b_i\) ,故讓 \(b_i = 10 - a_i\) 即可,相應地,可得 \(c_i = 0\)
類似地,在第二種情況中可得相應的 \(b_i = 0,~ c_i = a_i\)
下面開始 dp:\(f[i][0/1]\) 表示第 \(i\) 位不進位 / 進位下前 \(i\) 位的最小代價。
如果第 \(i-1\) 位沒有發生進位,那麼第 \(i\) 位沒有受到影響,直接針對上面的討論進行轉移即可。
如果發生進位,那麼第 \(i\) 位的 \(a_i\) 相當於 \(a_i+1\) 類似地進行轉移。
結合轉移方程理解:
\[f[i][0]=min(f[i-1][0]+a[i], ~f[i-1][1]+a[i]+1) \]\[f[i][1]=min(f[i-1][0]+10-a[i],~ f[i-1][1]+10-1-a[i]); \]程式碼:
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
int t(char ch){ // char 轉 int
return ch-'0';
}
const int N=1e6+5;
int f[N][2];
int main(){
string s; cin>>s; int n=s.size(); reverse(s.begin(), s.end()); s=' '+s;
f[0][1]=1, f[0][0]=0;
rep(i,1,n){
f[i][0]=min(f[i-1][0]+t(s[i]), f[i-1][1]+t(s[i])+1);
f[i][1]=min(f[i-1][0]+10-t(s[i]), f[i-1][1]+10-1-t(s[i]));
}
cout<<min(f[n][1]+1, f[n][0]);
return 0;
}