【Codeforce】 #643 div2

传送门

A. Sequence with Digits

题意

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

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

\(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\n",ans);
    }
}

C. Count Triangles

题意

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

数据范围

\(1 \leq A \leq x \leq B\leq y \leq C \leq z\leq D \leq10^{5}\)

题解

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

\[\because x+y=sum \]

\[\therefore y=sum-x \]

\[\because B \leq y \leq C \]

\[\therefore B \leq sum-x \leq C \]

\[\therefore 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\)

数据范围

\(1\leq N\leq S\leq 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\)

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

数据范围

\(1\leq 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;
}
posted @ 2020-05-20 18:38  Hyx'  阅读(209)  评论(0)    收藏  举报