CodeForces Round 957 (Div3)

蒟蒻找了一些简单题做了而已,别太在意……

比赛链接

CodeForces Round 957 (Div3)

A. Only Pluses

题意

三个正整数 a,b,c,有五次操作机会。

每次操作:

  • 选取 a,b,c 中任意一个数,将这个数加上一。

要求最大化 a×b×c

思路

很直接的贪心题。

假设有三个正整数 x,y,z,给其中的某一个数加上一,那么其乘积就是 (x+1)yzx(y+1)zxy(z+1)

要使乘积最大,那么这个加一的数一定是 x,y,z 中最小的那个数。

以此类推,五次操作中,我们必须贪心地选取 a,b,c 中最小的数。

为了省时省力,我们可以用小根堆来维护。

代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t,ans=1;cin>>t;
    priority_queue<int,vector<int>,greater<int> >q;
    while(t--){
        ans=1;for(int i=1,x;i<=3;i++)cin>>x,q.push(x);
        for(int i=1,t;i<=5;i++)
            t=q.top(),q.pop(),t++,q.push(t);
        for(int i=1;i<=3;i++)ans*=q.top(),q.pop();
        cout<<ans<<endl;
    }
    return 0;
}

B. Angry Monk

题意

给定长度为 k 的序列 {ak} 和正整数 n,保证 ai=n,每次可以进行一下两种操作:

  • 选定一个 ai(ai>1),将其分裂成 ai11

  • 选定 aiaj,满足 ai=1,将 aiaj 合并为一个 aj+1

求将序列长度变为 1最小操作次数。

思路

依然是贪心

如果两个数可以合并,当且仅当其中一个数为 1

考虑 k=2 的情况,假设序列中两个元素为 p,q(p>q),那么它的最小操作步数就是 2q1,即先将 q 分裂为 q1,再让这 q1p 合并。

以此类推,我们可以将序列先排序,把其中最小的 k1 个元素分别分解为 1,在让它们和最大的元素合并。

这样就能做了。

但继续想想,可以想到一个公式:

ans=nmax{ai}(k1)+nmax{ai}

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,a[100001];
void solve(){
    cin>>n>>k;for(int i=1;i<=k;i++)cin>>a[i];
    sort(a+1,a+k+1);
    cout<<n-a[k]-(k-1)+n-a[k]<<endl;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;while(t--)solve();
    return 0;
}

C. Gorilla and Permutation

题意

给定正整数 n,m,k,假设有一个关于 n 的排列 {an},那么 f(i)=j=1iai|aik,g(i)=j=1iai|aim

需要求一个 n 的排列,最大化 i=1nf(i)i=1ng(i)

思路

依然是贪心

在求两个正整数的最大差时,有一种思路就是在最大化被减数的同时最小化减数,这道题就可以用这种思路。

首先考虑如何最大化 i=1nf(i)。易得我们只需要在排列前端把 kn 从大到小排序即可。

其次考虑如何最小化 i=1ng(i)。易得我们只需要在排列末端把 1m 从小到大排序即可。

注意到 k>m,所以这两个操作并不交叉。至于那些大于 m 又小于 k 的数,随便放就行了。

直白地,对于给定的 n,m,k,我们给出的排列应当是:

n,n1,...,k+1,k,...,1,2,...m1,m

代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while(t--){
        int n,m,k;cin>>n>>m>>k;
        for(int i=n;i>m;i--)cout<<i<<' ';
        for(int i=1;i<=m;i++)cout<<i<<' ';
        cout<<endl;
    }
    return 0;
}

D. Test of Love

题意

A 愿意为 B 做任何事,甚至游过鳄鱼出没的沼泽。我们决定考验一下这份爱。A 必须游过一条长 n 米的河。他需要从 0 游到 n+1

最初,A 在左岸,需要到达右岸。它们分别位于 0n+1 米。这条河可以表示为 n 段,每段长度为 1 米。每个片段要么包含一个圆木 'L',要么包含一个鳄鱼 'C',要么包含一个水 'W'。A 可以移动如下:

  • 如果他在岸上或在圆木上,他可以向前跳不超过 m(1m10) 米。
  • 如果他在水里,他只能游到下一个河段(或者如果他在第 n 米处,他只能游到河岸)。
  • A 在任何情况下都不能带着鳄鱼降落在分段上

确定 A 是否能到达右岸。

思路

模拟贪心,好像很多 Div3 的题都是这样。

先来个分类讨论,假设当前为 i,假设输入的字符串为 c,那么:

  • ci='L',那么他可以向前跳最多 m 格,因为他最多只能游 k 格,所以我们可以贪心地尽量选择圆木。如果往后的 m 格都没有圆木,那么就跳进离 i 最远的水里。如果连水都没有,只有鳄鱼,那么输出 NO

  • ci='W',那么操作就很简单了,直接从 i 开始向后枚举,如果可以到达圆木,那么就站在圆木上,如果到达不了,那么输出 NO

我们可以把 c0cn+1 看作是个圆木。

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
char c[200005];
void solve(){
	memset(c,0,sizeof(c));
    cin>>n>>m>>k;c[0]='L',c[n+1]='L';
    for(int i=1;i<=n;i++)cin>>c[i];
    for(int i=0;i<=n+1;){
        bool b=0;
        if(i==n+1){cout<<"YES"<<endl;return;}
        if(c[i]=='W'){
            for(int j=i+1,l=1;j<=n+1;l++,j++){
                if(c[j]=='C'){cout<<"NO"<<endl;return;}
                if(c[j]=='L'){
                    k-=l;
                    if(k<0){cout<<"NO"<<endl;return;}
                    i=j;break;
                }
            }
            continue;
        }
        for(int j=min(i+m,n+1);j>=i+1;j--)if(c[j]=='L'){i=j;b=1;break;}
        if(b)continue;
        for(int j=min(i+m,n+1);j>=i+1;j--)if(c[j]=='W'){i=j;b=1;break;}
        if(b)continue;
        cout<<"NO"<<endl;return;
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;while(t--)solve();
    return 0;
}

E. Novice's Mistake

题意

对于一个只含数字字符的字符串 n,求出两个正整数 a,b 满足:

  • a×nb=a×num{n}b

思路

很直接,小模拟

如果 n=1,那么直接从 19999 输出 a,b 即可。

注意到,若要满足上述条件,那么 a×nb 一定是 n前几位,用循环解决即可。

枚举 a×nb 的位数。假设当前枚举到位数为 l,当前数字为 k,那么联立方程组,易得 a=klnlen{n},b=a×len{n}l

注意细节,具体见代码。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while(t--){
    	int n;cin>>n;int x[601],cnt=601,k=0,sum=0,o=n,p;
    	if(n==1){
    		cout<<9999<<endl;
    		for(int i=1;i<=9999;i++)cout<<i+1<<' '<<i<<endl;
    		continue;
		}
    	while(o)sum++,o/=10;vector<pair<int,int>>v;
    	for(int i=1;i<=6;i++){int u=n;while(u)x[--cnt]=u%10,u/=10;}
    	for(int i=cnt,l=1;i<=600;i++,l++){
			k=k*10+x[i];if(k>10000*n)break;
			if((k-l)%(n-sum)==0){
				int a=(k-l)/(n-sum);
				if(a==0||a*sum-l==0)continue;
				v.push_back(make_pair(a,a*sum-l));
			}
		}
		cout<<(p=v.size())<<endl;
		for(int i=0;i<p;i++)cout<<v[i].first<<' '<<v[i].second<<endl;
	}
    return 0;
}

F. Valuable Cards

题意

给定序列 {an} 和正整数 x,保证序列中不含 x。将序列分为多块,使得每块满足:

  • 在这一块中挑选若干个整数,使得它们的乘积不可能x

最小化块数。

思路

很直接的贪心(吧)。因为块数要越少越好,所以每一块中的元素应当越多越好

我们先将 x 分解因数,以便快速查询。接下来枚举每一个块,枚举 x 的因数,如果当前枚举的 ajx 因数的因数,那么查询一下当前这一块中是否有另外一个整数与 aj 相乘等于 x 的因数,如果有,那就将这个 x 的因数存入查询中,最后再将 aj 自身存入查询。

每一次枚举过后都要考虑查询中有没有 x,如果有的话,那么就重新开始枚举下一块ans++

我们定义一个 unordered_map 来完成上述操作。由于 unordered_map 的平均复杂度为 O(1),所以总时间复杂度应该是 O(nx)

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,x,a[100001];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while(t--){
        int ans=0,cnt=0;int num[1001];
        cin>>n>>x;for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=x;i++)if(x%i==0)num[++cnt]=i;
        for(int i=1;i<=n;i++){
            ans++;unordered_map<int,bool>p;
            for(int j=i;j<=n;j++){
            	vector<int>v;
                for(int k=1;k<=cnt;k++){
                    if(num[k]%a[j]==0&&p.count(num[k]/a[j]))
                        v.push_back(num[k]);
                }
                for(int i=0;i<v.size();i++)p.emplace(v[i],0);
				p.emplace(a[j],0);
                if(p.count(x)){i=j-1;break;}
                else if(j==n){i=j;break;}
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
posted @   SnapYust  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示