【Codeforce】 #643 div2

传送门

A. Sequence with Digits

题意

给定(a,k), 每次使得(a)进行如下计算:

[a_{n+1}=a_{n}+min operatorname{Digit}left(a_{n} ight) cdot max operatorname{Digit}left(a_{n} ight) ]

(k)次计算后的值

数据范围

(1 leq a_{1} leq 10^{18}, 1 leq K leq 10^{16})

题解

在一定次数的计算后,出现0就不会改变了,直接break

Code

cpp
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define ll long long
int _;
int main(){
    for(scanf("%d",&_);_;_--){
        ll a,k;
        cin>>a>>k;
        bool flag=1;
        k--;
        while(k-- && flag){
            ll t=a;
            ll mn=1e18,mx=0;         
            while(t){
                ll x=t%10;
                //if(x==0) {flag=0;break;}
                t/=10;
                mn=min(mn,x);
                mx=max(mx,x);
            }
            if(mn==0 || mx==0) break;
            a+=mn*mx;
        }
        cout<<a<<endl;
    }
}

B. Young Explorers

题意

给定(N)个人,每个人有一个经验值(e),每个人只能存在于人数大于等于他经验值得队,求出可以分配的最大的队伍

数据范围

(1 leq N leq 2 cdot 10^{5})
(1 leq e_{i} leq N)

题解

从小到大贪心,贪心的策略是不多分配,可以分配一个群组就分配恰好的数量,
维护一个当前的人数即可,
存在一个单调性,即当前人之前剩下的人数一定不会大于当前人的经验值

Code

cpp
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define ll long long
int _;
const int N=2e5+10;
int e[N];
int main(){
    for(scanf("%d",&_);_;_--){
        unordered_map<int,int>p;
        set<int>s;
        int n;
        scanf("%d",&n);
        rep(i,0,n) {int x;scanf("%d",&x); p[x]++; s.insert(x);}
        int now=0;
        int ans=0;
        for(auto it:s){
            now+=p[it];
            if(it <= now) {
                ans+=now/it;
                now-=(now/it * it); 
            }
        }
        printf("%d
",ans);
    }
}

C. Count Triangles

题意

给定(A,B,C,D)求一个三角形的三边(x,y,z),满足(A leq xleq B leq yleq Cleq z leq D),求在合法范围内能构成多少种三角形

数据范围

(1 leq A leq x leq Bleq y leq C leq zleq D leq10^{5})

题解

用较小的两边之和(sum)大于第三边判断三角形是否合法,枚举小的两边和, 求出在合法的范围内第三条边的个数为(min(D , sum-1) - C +1)
再求出两条边的和为(i)的个数,

[ecause x+y=sum ]

[ herefore y=sum-x ]

[ecause B leq y leq C ]

[ herefore B leq sum-x leq C ]

[ herefore sum-C leq x leq sum-B为和为x+y的x和y的个数 ]

Code

cpp
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define ll long long
int main(){
    ll a,b,c,d;
    cin>>a>>b>>c>>d;
    ll ans=0;
    for(ll i=a+b;i<=b+c;i++){
        ll z=min(d,i-1)-c+1,t=min(i-b,b)-max(i-c,a)+1;
        if(z<0 || t<0) continue;
        ans+=z * t;
    }
    cout<<ans<<endl;
}

D. Game With Array

题意

构造一个数组长度为(N),和为(S) 的数组,一个(K), 问是否能构造出使得所有的子序列和不等于(K)(S-K)

数据范围

(1leq Nleq Sleq 10^{6})
(0 leq K leq S)

题解

(n-1)全填(2),剩下的如果(leq 1)则无法构造出,否则只要选择(K=1)即可

Code

cpp
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define ll long long
int main(){
    int n,s;
    cin>>n>>s;
    int s_=s-(n-1)*2;
    if(s_<=1){puts("NO");return 0;}

    vi ans;
    rep(i,0,n-1) ans.pb(2);
    ans.pb(s_);
    puts("YES");
    for(auto it: ans)
        cout<<it<<' ';
    puts("");
    cout<<"1"<<endl;
}

E. Restorer Distance

题意

给定(N)堆盘的高度(h_{i}),三个操作,

  • 添加一个到一个的最上面代价(A)
  • 移除一个最上面的代价(B)
  • 将一个的最上面的移动到另一个上代价(M)

求出让所有的堆高度相同的最小代价

数据范围

(1leq N leq 10^{5})
(0 leq h_{i} leq 10^{9})
$ 0 leq A, R, M leq 10^{4}$

题解

首先可以将(M)换成(min(M,A+B)),可以看出来代价关于高度h是一个单谷函数,因此三分求最小值

Code

cpp
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second 
#define ll long long
#define pb push_back
typedef pair<long long,long long> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef double db;
const ll mod=1e9+7;
ll powmod(ll a,ll b,ll p){ll res=1;a%=p;while(b){if(b&1) res=res*a%p;a=a*a%p;b>>=1;}return res;}
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
const int N=1e5+10;
ll h[N];
ll n,a,r,m;
ll cal(ll x){
    ll add=0,del=0;
    for(int i=0;i<n;i++) {
        if(h[i]>x) del+=h[i]-x;
        if(h[i]<x) add+=x-h[i];
    }
    ll delta=abs(del-add),move=min(del,add);
    ll res=0;
    res+=move*m;
    if(del>add) res+=delta*r;
    if(add>del) res+=delta*a;
    return res;
}
int main(){
    cin>>n>>a>>r>>m;
    m=min(m,a+r);
    for(int i=0;i<n;i++) cin>>h[i];
    ll l=0,r=1e9;
    while(l<r){
        ll lmid=(l*2+r)/3,rmid=(r*2+l+2)/3;
        if(cal(lmid)<cal(rmid)) r=rmid-1;
        else l=lmid+1;
    }
    cout<<cal(l)<<endl;
}
原文地址:https://www.cnblogs.com/hhyx/p/12925350.html