Codeforces Round #643 (Div. 2) ABCDE題解

如果有什麼講的不清楚的歡迎留言私信交流~

A. Sequence with Digits(思維)

題意: 給定一個數x, 每次變化是 x = x + 最高數位 * 最低數位,求出k-1次變化後的值。

思路: 最大值只要初始不是0那麼就不會是0,而最小值一直取min,最後肯定會變成0,當最小值出現0就不再需要變化。

#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
 
const int manx=1e3+5;
const int N=1e6+5;
 
ll do1(ll x){
    ll ans=9;
    while(x){
        if(x%10<ans)  ans=x%10;
        x/=10;
    }
    return ans;
}
ll do2(ll x){
    ll ans=0;
    while(x){
        if(x%10>ans)  ans=x%10;
        x/=10;
    }
    return ans;
}
int main(){
    io;
    ll p; cin>>p;
    while(p--){
        ll a,b; cin>>a>>b;
        for(int i=1;i<b;i++){
            ll x=do1(a),y=do2(a);
            a=a+x*y;
            if(x==0) break;
        }
        cout<<a<<endl;
    }
    return 0;
}

B. Young Explorers(貪心)

題意: 給出一個數組,每個元素代表所在的組人數的最小值,問最多可以組成多少個組。

思路: 貪心做法,小的儘可能組成多組,大的和剩餘的小的再湊一組,用個桶排序,記得每次詢問後清空桶,這裏不要用memset,cf 容易 tle 。

#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
 
const int manx=1e3+5;
const int N=1e6+5;
 
ll a[N],b[N];
 
int main(){
    io;
    ll p; cin>>p;
    while(p--){
        ll n;  cin>>n; ll m=0;
        for(int i=1;i<=n;i++){
            ll x; cin>>x;
            if(!b[x]) a[++m]=x;
            b[x]++;
        }
        sort(a+1,a+1+m);
        ll ans=0,res=0;
        for(int i=1;i<=m;i++){
            ans+=b[a[i]]/a[i];
            res+=b[a[i]]%a[i];
            if(res>=a[i]){
                ans+=res/a[i];
                res%=a[i];
            }
        }
        cout<<ans<<endl;
        for(int i=1;i<=n;i++) b[i]=0;
    }
    return 0;
}

C. Count Triangles (思維)

題意:給出 A<=X<=B<=Y<=C<=Z<=DA<=X<=B<=Y<=C<=Z<=D,求出 xyz 組成三角形的個數。

思路:枚舉 X+Y 的和,這樣只要確定了 X 和 Z ,那麼 Y 唯一。
由於是賽後補的題,詳細見代碼註釋吧。

#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;

const int manx=1e3+5;
const int N=1e6+5;

int main(){
    io;
    ll a,b,c,d,x,y,z;
    cin>>a>>b>>c>>d;
    ll ans=0;
    for(ll i=c+1;i<=c+d;i++){ //這裏是枚舉x+y的和
        ll l=max(a,i-c),r=min(b,i-b); // l是x的最小值 r是x的最大值
        if(l>r) continue;
        ans+=(r-l+1)*(min(d+1,i)-c); // r-l+1是x的取值個數  後面同理是z的取值個數
    }
    cout<<ans;
    return 0;
}

D. Game With Array(構造)

題意:給定n代表數組的長度,s代表數組元素的累加和,問有沒有方法 構造一個長度爲n的數組 使累加和爲s 並且可以取一個非空數組和=k 或者s-k。

思路:

  1. 首先如果n>s肯定構造不出來,而 n==s 肯定會有一個k滿足條件(全1)。
  2. 其他情況的話,先構造出 n - 1 個1,剩下一個就是 s-n+1。
  3. 因爲前 n-1 都是1,剩下一個元素大於1,所以無論如何都無法構造一個 k==n 。
#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
 
const int manx=1e3+5;
const int N=1e6+5;
 
ll a[N],b[N];
 
int main()
{
	//io;
	ll n,s; cin>>n>>s;
	ll d=s-(n-1);
	ll x=n-1;
	if(x+1>=d) puts("NO");
	else
	{
		puts("YES");
		ll ans=x+1;
		for(int i=1;i<n;i++)
            cout<<1<<" ";
        cout<<d<<endl;
		cout<<ans<<endl;
	}
	return 0;
}

E. Restorer Distance(三分)

題意:給定n個柱子高度不一,可操作增高1單位花費a,壓低一單位花費r,高出部分單位移動給需增高部分單位花費m,求每個柱子一樣高的最小花費。

思路:三分模板題,如果高度爲最低的柱子或者高度爲最高的柱子肯定花費大於等於中間的某個點的花費,這樣就是開口向下的函數,主要就是判斷函數裏面不同,就是要考慮什麼時候把高出的部分移動到低的柱子就是花費m:

  1. 如果a+r<m 就沒有必要進行這種操作,直接計算出每個柱子補到x 的高度差之和,mi 就是小於x的高度差之和,ma就是大於x 與 x的高度差之和,那麼貢獻就是mia+marmi*a+ma*r
  2. 如果使用m的話就是 min(mi,ma)mmin(mi,ma)*m 然後加上多餘的部分。
#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
 
const int manx=1e3+5;
const int N=1e6+5;
 
ll n,a,r,m;
ll h[N];
ll l=1,rr=0;
 
ll pd(ll x){
    ll ans=0;
    if(m>=a+r){
        for(int i=1;i<=n;i++){
            if(h[i]>x) ans+=(h[i]-x)*r;
            if(h[i]<x) ans+=(x-h[i])*a;
        }
    }
    else{
        ll mi=0,ma=0;
        for(int i=1;i<=n;i++){
            if(h[i]>x) ma+=h[i]-x;
            if(h[i]<x) mi+=x-h[i];
        }
        ll ms=min(mi,ma);
        ans+=ms*m;
        ans+=(mi-ms)*a;
        ans+=(ma-ms)*r;
    }
    return ans;
}
 
int main(){
    io;
    cin>>n>>a>>r>>m;
    for(int i=1;i<=n;i++) cin>>h[i];
    sort(h+1,h+1+n); rr=h[n];
    ll x=1e18;
    while(l<=rr){
        ll lm=l+(rr-l)/3,rm=rr-(rr-l)/3;
        ll w1=pd(lm),w2=pd(rm);
        x=min(w1,x); x=min(w1,x);
        if(w1<=w2) rr=rm-1;
        else l=lm+1;
    }
    cout<<x;
    return 0;
}

以上,如果有什麼講的不清楚的歡迎留言私信交流~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章