Codeforces Round #552 (Div. 3) A(数学)B(模拟)C(模拟)D(模拟)E(模拟)F(简单DP)G(最小LCM)

Consest:https://codeforces.com/contest/1154

这场打的是真惨啊C题卡了半天,D题样例始终对不上,E题满脑子骚操作就是不会写。被吊打,疯狂掉分,滚粗CF。

这次的题好多模拟啊。。。

A. Restoring Three Numbers(数学)

题目链接:https://codeforces.com/contest/1154/problem/A

题目大意:三个数a,b,c,然后你有a+b,a+c,b+c,a+b+c四个结果。让你求出原来的a,b,c;

思路:四个方程三个未知数,联立得出a||b||c=(a+b+c)-(a+b)||(a+c)||(b+c);输出即可。

ACCode:

int main(){
	int a[5];
	for(int i=1;i<=4;++i){
		scanf("%d",&a[i]);
	}sort(a+1,a+1+4);
	int x1=a[4]-a[1];
	int x2=a[4]-a[2];
	int x3=a[4]-a[3];
	printf("%d %d %d\n",x1,x2,x3);
}

B. Make Them Equal(暴力)

题目链接:https://codeforces.com/contest/1154/problem/B

题目大意:给出n个数的数组a,让你选择一个数d对于所有的a[i](加上||减去||d||不改变)之后变成一个数。输出最小的d

思路:由于数据范围非常小,暴力就好了。

ACCode:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
 
#include<stdio.h>
#include<string.h>
#include<math.h>
 
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define LL long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e4+10;
const int INF32=0x3f3f3f3f;
const LL INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);

int a[MAXN];
int n;

int main(){
	while(~scanf("%d",&n)){
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
		}sort(a+1,a+1+n);
		if(a[1]==a[n]){
			printf("0\n");
			continue;
		}
		int ans=INF32;
		for(int i=0;i<=200;++i){//mid is i
			int res=INF32;
			for(int j=1;j<=n;++j){
				if(a[j]==i) continue;
				if(res==INF32) res=abs(a[j]-i);
				if(res!=abs(a[j]-i)){
					res=-1;
					break;
				}
			}
			if(res!=-1) ans=min(ans,res);
		}printf("%d\n",ans==INF32?-1:ans);
	}
}

C. Gourmet Cat(模拟)

题目链接:https://codeforces.com/contest/1154/problem/C

题目大意:三种食物,鱼在周1,4,7吃,兔子在周2,6吃,鸡在周3,5吃。问一开始分别准备了a,b,c数量的食材。最多能够坚持多少天不不充食材。输出最长的天数。(一周过完跟着一周)

思路:首先一周分别花费3,2,2。所以按照这个数量得出多少个整周。然后对于剩下的小天数分别计算即可。(辣鸡的我只会枚举,据说有大佬一个循环就出来了,以后再看吧QAQ)总共4*3*3=36种情况好难受。

ACCode:

int main(){
	int a,b,c;
	while(~scanf("%d%d%d",&a,&b,&c)){
		int minn=min(a/3,min(b/2,c/2));
		a=a-3*minn;b=b-2*minn;c=c-2*minn;
		int ans=minn*7,last=min(a,min(b,c));
		if(a==0){
			if(b==0){
				if(c==0) ans=ans;
				else ans+=1;
			}
			else{
				if(c==0) ans+=1;
				else ans+=2;
			}
		}
		else if(a==1){
			if(b==0){
				if(c==0) ans+=1;
				else if(c==1) ans+=2;
				else ans+=3;
			}
			else if(b==1){
				if(c==0) ans+=2;
				else if(c==1) ans+=3;
				else ans+=4;
			}
			else{
				if(c==0) ans+=2;
				else if(c==1) ans+=3;
				else ans+=5;
			}
		}
		else if(a==2){
			if(b==0){
				if(c==0||c==1) ans+=2;
				else ans+=3;
			}
			else if(b==1){
				if(c==0) ans+=3;
				else if(c==1) ans+=4;
				else ans+=5;
			}
			else{
				if(c==0) ans+=4;
				else if(c==1) ans+=5;
				else ans+=6;
			}
		}
		else{
			if(b==0){
				if(c==0||c==1) ans+=2;
				else ans+=3;
			}
			else if(b==1){
				if(c==0) ans+=3;
				else if(c==1) ans+=5;
				else ans+=6;
			}
			else{
				if(c==0) ans+=4;
				else if(c==1) ans+=6;
				else ans+=7;
			}
		}printf("%d\n",ans);
	}
}

D. Walking Robot(模拟)

题目链接:https://codeforces.com/contest/1154/problem/D

题目大意:一个n长度的路段,0代表没有阳光,1代表有阳光。机器人有两块电池a,b(容量)电池一开始的时候是满的。机器人向前走一步需要花费一格电,当机器人走过1道路的时候,可以选择电池a减少1电量,电池b加1点电量(但是b如果是满的就无法增加)。当经过0道路时,可以选择消耗a电池||b电池。问机器人最多走多远。

思路:模拟即可。很明显,先要用电池b的点。

ACCode:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
 
#include<stdio.h>
#include<string.h>
#include<math.h>
 
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define LL long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ˮӡ
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=2e5+10;
const int INF32=0x3f3f3f3f;
const LL INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);

int s[MAXN];
int n,b,a;

int main(){
	while(~scanf("%d%d%d",&n,&a,&b)){
		int c=a,d=b;
		for(int i=1;i<=n;++i){
			scanf("%d",&s[i]);
		}int flag=0;
		int i;
		for(i=1;i<=n;++i){
			if(s[i]){
				if(d<b){
					if(c>0){
						++d;--c;
					}
					else{//c==0
						--d;
					}
				}
				else{//d==b
					--d;
				}
			}
			else{//0
				if(d>0) --d;
				else --c;
			}
			if(c==0&&d==0) break;
		}printf("%d\n",i==n+1?n:i);
	}
}

E. Two Teams(模拟)

题目链接:https://codeforces.com/contest/1154/problem/E

题目大意:n个元素的数组,每个元素都有自己的权值,两个人轮流从中选择最大的元素,同时选择最大元素为中心,k半径的元素,选择出的元素被移除数组。问最后每个元素的归属。

思路:一开始没什么思路,毕竟数组有点大,而且也不知道怎么搞,后来想起了之气yy的一个算法,使用两个数组L,R记录该节点被L~R区间包含,然后之后碰到该节点之后直接跳过就好了。没想到就过了,后来估算了一下复杂度,似乎删掉之后就变少了。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=2e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;

int a[MAXN],Vis[MAXN];
int L[MAXN],R[MAXN];
int Res[MAXN];
Pair b[MAXN];
int n,k;

int Cmp(Pair x,Pair y){
	return x.second>y.second;
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;++i) L[i]=R[i]=i;
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		b[i]=make_pair(i,a[i]);
	}sort(b+1,b+1+n,Cmp);
	for(int i=1,Kind=1;i<=n;++i){
//		cout<<b[i].first<<" "<<b[i].second<<endl;
		if(Vis[b[i].first]) continue;
		int temp=b[i].first;
		Vis[temp]=Kind&1?1:2;Kind++;//ˢ�¸õ� 
		int ql=temp,qr=temp,tot=0;
		for(int j=1,l=1;j<=k;++j){
			int tempx=temp-l;
			while(tempx>=1&&Vis[tempx]) tempx=L[tempx]-1;//���ڣ��ߵ��߾� 
			if(tempx==0){
				ql=1;break;
			}Res[++tot]=tempx;
			Vis[tempx]=Vis[temp];
			l=temp-tempx;ql=tempx;
		}
		for(int j=1,r=1;j<=k;++j){
			int tempx=temp+r;
			while(tempx<=n&&Vis[tempx]) tempx=R[tempx]+1;
			if(tempx==n+1){
				qr=n;break;
			}Res[++tot]=tempx;
			Vis[tempx]=Vis[temp];
			r=tempx-temp;qr=tempx;
		}
		for(int j=1;j<=tot;++j){
			L[Res[j]]=ql;R[Res[j]]=qr;
		}L[temp]=ql;R[temp]=qr;
//		cout<<endl<<b[i].first<<" "<<b[i].second<<":  "<<endl;
//		for(int i=1;i<=n;++i){
//			cout<<Vis[i];//<<L[i]<<" "<<R[i]<<endl;
//		}
	}
	for(int i=1;i<=n;++i){
		printf("%d",Vis[i]);
	}printf("\n");
}

F. Shovels Shop(简单DP)

题目链接:https://codeforces.com/contest/1154/problem/F

题目大意:给出n个铲子的价格,m个优惠方式,要买k个铲子。优惠是满a个,花费最少的b个就会免费。问最少花费多少钱。

思路:一道明显的DP,得出买每个铲子的最小花费,然后递推即可。买i个铲子花费的最小值就是(买j个铲子的花费+(买i个铲子的花费-(买j个铲子的花费+满减的花费))。

状态转移方程就是:DP[i]=min(DP[i],DP[j]+sum[i]-sum[j+mix[i-j]])

ACCode:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
 
#include<stdio.h>
#include<string.h>
#include<math.h>
 
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define LL long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=2e5+10;
const int INF32=0x3f3f3f3f;
const LL INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);

int a[MAXN],b[MAXN];
int mix[MAXN],DP[MAXN];
int n,m,k;

int main(){
	while(~scanf("%d%d%d",&n,&m,&k)){
		clean(mix,0);
		for(int i=1;i<=n;++i) scanf("%d",&a[i]);
		sort(a+1,a+1+n);
		for(int i=1;i<=n;++i) b[i]=b[i-1]+a[i];
		for(int i=1;i<=m;++i){
			int x,y;scanf("%d%d",&x,&y);
			mix[x]=max(mix[x],y);
		}
		for(int i=1;i<=k;++i){
			DP[i]=INF32;
			for(int j=0;j<i;++j){
				DP[i]=min(DP[i],DP[j]+b[i]-b[j+mix[i-j]]);
			}
		}printf("%d\n",DP[k]);
	}
}

G. Minimum Possible LCM(最小LCM)

题目链接:https://codeforces.com/contest/1154/problem/G

题目大意:给出n个数,从中选择两个数,使其的LCM最小,输出最小的LCM。LCM:最小公倍数。

思路:首先用排除法,暴力肯定不行。查看题解:枚举所有的GCD,然后根据其GCD找出存在的两个数。得出LCM,刷新ans。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e6+10;
const int MAXM=1e7+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;

int a[MAXN],Vis[MAXM];
int n;

int main(){
	while(~scanf("%d",&n)){
		clean(Vis,0);
		ll ans=1e18;int ans1=0,ans2=0;
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
			if(Vis[a[i]]&&ans>a[i]){
				ans=a[i];ans1=Vis[a[i]];ans2=i;
			}
			if(Vis[a[i]]==0) Vis[a[i]]=i;
		}
		for(int i=1;i<MAXM;++i){//GCD
			if(i>ans) break;
			int res1=0,res2=0;
			for(int j=i;j<MAXM;j+=i){
				if(Vis[j]==0) continue;
				if(res1==0) res1=Vis[j];
				else{
					if(ans>1ll*a[res1]*j/i){
						ans=1ll*a[res1]*j/i;
						res2=Vis[j];
						ans1=res1;ans2=res2;
					}break;
				}
			}
		}
		if(ans1>ans2) swap(ans1,ans2);
		printf("%d %d\n",ans1,ans2);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/89390644