2021-07-21

Codeforces Round #690 (Div. 3)(A~F)

A题
简单模拟,按照题目写

#include<iostream>
using namespace std;
int n,t,a[500];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)cin>>a[i];
		for(int i=1,j=n;i<j;i++,j--)
		cout<<a[i]<<' '<<a[j]<<' ';
		if(n%2==1)cout<<a[n/2+1];
		cout<<endl;
	}
}

B题
给定一个字符串,可以进行一次操作,删除一个子串,使得剩下的为2020
因为只能删除一次,所以只会保留前i个字符和后4-i个字符 i取0 1 2 3 4 除此之外都不成立 所以直接判断前i个字符和后4-i个字符即可

#include<iostream>
using namespace std;
int t;
string s;
int main()
{
	cin>>t;
	while(t--)
	{
		int n,f=0;
		cin>>n>>s;
		for(int i=0;i<=4;i++)
		{
			string s2;
			for(int k=0;k<i;k++)s2.push_back(s[k]);
			for(int k=n-(4-i),add=1;add<=4-i;add++,k++)s2.push_back(s[k]);
			if(s2=="2020")f=1;
		}
		if(f)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
}

C题
给定一个数x,找出最小的数使得各位数字之和为x,切各位数字不相同
这个数字最多只有9位,1到9的和为45,所以x>45则输出-1 否则应该选更大的数,因为会使位数尽量短,也就是数会越小

#include<iostream>
using namespace std;
int n,t;
int main()
{
	cin>>t;
	while(t--)
	{
		int st[10]={0};
		cin>>n;
		if(n>45)cout<<-1<<endl;
		else
		{
			while(n)
			{
			for(int i=9;i>=1;i--)
			{
				if(i<=n)
				{
					st[i]=1;
					n-=i;
				}
			}
			}
			for(int i=1;i<=9;i++)
			if(st[i])cout<<i;
			cout<<endl;
		}
	}
}

D题
有一个数组,每次可以将相邻的两个数合并,也就是将其划分成若干个部分,每部分的和都相同,一个部分内有x个数就进行了x-1次合并,求最小合并次数
第一个数属于的部分有n种情况,1~1 1~2 1~3 … 1~n,下面考虑后面的数能否组成第一个部分的和即可 复杂度 n^2

#include<iostream>
using namespace std;
long long a[100010],sum[3010],t,n;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		sum[0]=0;
		for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];
		long long ans=n;
		for(int i=1;i<=n;i++)
		{
			long long f=0,x=sum[i],now=0,add=0;
			for(int i=1;i<=n;i++)
			{
				if(now+a[i]<x)now+=a[i],add++;
				else if(now+a[i]==x)now=0;
				else 
				{
					f=1;
					break;
				}
			}
			if(f==0&&now==0)ans=min(ans,add);
		}
		cout<<ans<<endl;
	}
}

E1&E2
E1和E2 做法相同,e1是e2的简单版,实际上难度差不多,直接给出e2的做法
题意:给定一个数组,选择m个数 这m个数的最大值和最小值的差要求小于等于k,问一共有多少组选法
先将数组排序,对于选择了ai的数 可以二分找ai+k的下标j 选择了ai的所有选法就是 在i+1到j中选择m-1个 很明显考虑的是选择了ai的情况,所以考虑完1到n即没有重复也没有遗漏 对于每种情况组合数即可

在这里插入图片描述
E1

#include<iostream>
#include<algorithm>
using namespace std;
long long a[200010],sum[3010];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)cin>>a[i];
		sort(a+1,a+1+n);
		long long ans=0;
		for(int i=1;i<=n;i++)
		{
			int r=upper_bound(a+1,a+1+n,a[i]+2)-a;
			r--;
			long long l=r-i;
			if(a[r]-a[i]<=2&&l>=2)
			ans+=l*(l-1)/2;
		}
		cout<<ans<<endl;
	}
}

E2

#include<iostream>
#include<algorithm>
using namespace std;
long long a[200010],n,m,k;
const long long mod=1e9+7;
long long j[200010],nj[200010];
long long pows(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans%mod;
}
long long c(long long a,long long b)
{
	return j[a]*nj[b]%mod*nj[a-b]%mod;
}
int main()
{
	 j[0]=nj[0]=1;
    for(int i=1;i<=200000;i++)j[i]=j[i-1]*i%mod;
    for(int i=1;i<=200000;i++)nj[i]=nj[i-1]*pows(i,mod-2)%mod;
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m>>k;
		for(int i=1;i<=n;i++)cin>>a[i];
		sort(a+1,a+1+n);
		long long ans=0;
		for(int i=1;i<=n;i++)
		{
			int r=upper_bound(a+1,a+1+n,a[i]+k)-a;
			r--;
			long long l=r-i;
			if(a[r]-a[i]<=k&&l>=m-1)
			ans=(ans+c(l,m-1))%mod;
		}
		cout<<ans<<endl;
	}
}

F题
题意:有n个区间,删除x个区间,满足只要有一个区间和其他区间至少有一个交点,求x的最小值
先按照左端点排序
在这里插入图片描述
对于每一个区间 后面有多少区间与它有交点可以二分,前面有多少个区间与它有交点,可以差分,每次二分后,设为j说明i与(i+1,j)有交点,i+1,j进行加以差分即可

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
struct node
{
	int x,y;
}a[200010];
int n;
int cha[200010],sum[200010];
bool cmp(node a,node b)
{
	if(a.x==b.x)return a.y<b.y;
	return a.x<b.x;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i].x,&a[i].y);
		sort(a+1,a+1+n,cmp);
		for(int i=1;i<=n;i++)
		{
			int l=i+1,r=n;
			while(l<r)
			{
				int mid=l+r+1>>1;
				if(a[mid].x<=a[i].y)l=mid;
				else r=mid-1;
			}// i+1,r
			if(a[l].x<=a[i].y)
			{
			
			cha[i+1]++;
			cha[r+1]--;
			sum[i]=r-i;
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)cha[i]+=cha[i-1];
		for(int i=1;i<=n;i++)
		ans=max(ans,cha[i]+sum[i]);
		printf("%d\n",n-ans-1);
		for(int i=1;i<=n+1;i++)
		sum[i]=0,cha[i]=0;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值