2021算法竞赛入门班第二节课【递归、分治、二分】练习题

华华给月月准备礼物【二分】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/23049
就是一个常见的二分模板

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5+10;
LL a[N],n,k;
bool check(int x)
{
    
    
	int cnt=0;
	for(int i=0;i<n;i++) cnt+=a[i]/x;
	if(cnt>=k) return true;
	return false;
}
int main(void)
{
    
    
	cin>>n>>k;
	for(int i=0;i<n;i++) cin>>a[i];
	LL l=0,r=1e9+10;
	while(l<r)
	{
    
    
		LL mid=l+r+1>>1;
		if(check(mid)) l=mid;
		else r=mid-1;
	}
	cout<<l;
	return 0;
}

The Biggest Water Problem【模拟】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/15173

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
    
    
	int n; cin>>n;
	while(n>=10)
	{
    
    
		int sum=0;
		while(n) sum+=n%10,n/=10;
		n=sum;
	}
	cout<<n;
	return 0;
}

Bits【递归模拟 / 未完成】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/201605


[NOIP2004]FBI树【树的后序遍历】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/16660

#include<bits/stdc++.h>
using namespace std;
int n;
string s;
void dfs(string s)
{
    
    
    if(s.size()>1)
    {
    
    
        dfs(s.substr(0,s.size()/2));
        dfs(s.substr(s.size()/2));
    }
    int cnt0=0,cnt1=0;
    for(int i=0;i<s.size();i++) 
        if(s[i]=='0') cnt0++;
        else cnt1++;
    if(cnt0&&cnt1) cout<<'F';
    else if(cnt0&&!cnt1) cout<<'B';
    else cout<<'I';
}
int main(void)
{
    
    
    cin>>n>>s;
    dfs(s);
    return 0;
}

[USACO 2009 Dec S]Music Notes【二分+前缀和】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/24866

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],n,m;
int main(void)
{
    
    
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
	while(m--)
	{
    
    
		int x; cin>>x;
		int l=1,r=n;
		while(l<r)
		{
    
    
			int mid=l+r>>1;
			if(a[mid]>=(x+1)) r=mid;
			else l=mid+1;
		}
		cout<<l<<endl;
	}
}

[NOIP2009]分数线划定【模拟】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/16625

#include<cstdio>
#include<algorithm>
using namespace std;
struct student
{
    
    
    int sum;//分数
    int id;//学号
}s[5005];
bool cmp(student a,student b)
{
    
    
    if(a.sum!=b.sum)
        return a.sum>b.sum;
    else
        return a.id<b.id;
     
}
int main(void)
{
    
    
    int n,m;//n代表总的人数 m代表志愿者人数
    int end_number;//进入面试的人数
    int end_score;//面试分数线
    int i;
    scanf("%d %d",&n,&m);
    end_number=m*1.5;
    for(i=0;i<n;i++)
    {
    
    
        scanf("%d %d",&s[i].id,&s[i].sum);
    }
    sort(s,s+n,cmp);//总的排序
    end_score=s[end_number-1].sum;//面试的分数线
    for(i=end_number;i<n;i++)//加上重分的人
    {
    
    
        if(s[i].sum==end_score)
            end_number++;
        else
            break;
    }
    printf("%d %d\n",end_score,end_number);
    for(i=0;i<end_number;i++)
    {
    
    
        printf("%d %d\n",s[i].id,s[i].sum);
    }
    return 0;
}

逆序数【归并排序】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/15163

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5+10;
LL a[N],b[N],n,res;
void merge_sort(int l,int r)
{
    
    
	if(l>=r) return;
	int i=l,mid=l+r>>1,j=mid+1;
	merge_sort(l,mid),merge_sort(mid+1,r);
	int k=0;
	while(i<=mid&&j<=r) 
	{
    
    
		if(a[i]<=a[j]) b[k++]=a[i++];
		else
		{
    
    
			res+=mid-i+1;
			b[k++]=a[j++];
		}
	}
	while(i<=mid) b[k++]=a[i++];
	while(j<=r) b[k++]=a[j++];
	for(int i=l,j=0;i<=r;i++,j++) a[i]=b[j];
}
int main(void)
{
    
    
	cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	merge_sort(0,n-1);
	cout<<res;
	return 0;
}

逆序对【组合数 / 推式子】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/14731
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int mod=1e9+7;
LL quick_mi(LL a,LL b, LL p)
{
    
    
	LL sum=1;
	while(b)
	{
    
    
		if(b&1) sum=sum*a%p; 
		b>>=1;
		a=(a*a)%p;
	}
	return sum%p;
}
int main(void)
{
    
    
	LL n; cin>>n;
	if(n==1) cout<<0;
	else if(n==2) cout<<1;
	else cout<<(n%mod)*((n-1)%mod)%mod*quick_mi(2,n-3,mod)%mod;
	return 0;
}

完全平方数【二分】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/14733

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
vector<LL>ve;
int main(void)
{
    
    
	for(LL i=0;i<=1e5;i++) ve.push_back(i*i);
	int n; cin>>n;
	while(n--)
	{
    
    
		LL a,b,l,r; cin>>a>>b;
		int len1=0,len2=0;
		l=0,r=ve.size()-1;
		while(l<r)
		{
    
    
			int mid=l+r>>1;
			if(ve[mid]>=a) r=mid;
			else l=mid+1;
		}
		len1=l;
		l=0,r=ve.size()-1;
		while(l<r)
		{
    
    
			int mid=l+r+1>>1;
			if(ve[mid]<=b) l=mid;
			else r=mid-1;
		}
		len2=l;
		cout<<len2-len1+1<<endl;
	}
	return 0;
}

[USACO 2010 Feb S]Chocolate Eating【二分】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/24724
注意的一点是: 开一个备用数组 只有满足条件时再保存答案 避免数组错乱保存
还需注意的是,当我们满足时,如果巧克力吃的天数不够,那么统一的最后一天吃。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef unsigned long long int LL;
LL a[N],s,n,m;
LL ans[N];
bool check(LL mid)
{
    
    
	LL len=1,temp=0;
	LL backup[N]={
    
    0};
	for(int i=1,j=1;i<=m;i++)//枚举天数
	{
    
    
		while(temp<mid&&j<=n) temp+=a[j],backup[j]=i,j++;
		if(temp<mid) return false;//不满足
		temp/=2;
	}
	memcpy(ans,backup,sizeof ans);
	return true;
}
int main(void)
{
    
    
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i],s+=a[i];
	LL l=0,r=s;
	while(l<r)
	{
    
    
		LL mid=l+r+1>>1;
		if(check(mid)) l=mid;
		else r=mid-1;
	}
	cout<<l<<endl;
	for(int i=1;i<=n;i++) 
	{
    
    
		if(!ans[i]) ans[i]=m;//天数不够
		cout<<ans[i]<<endl;
	}
	return 0;
}

第k小数【快排】

在这里插入图片描述
https://ac.nowcoder.com/acm/problem/207028

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
int a[N],t,n,k;
inline int read(){
    
    
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
    
    
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
    
    
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
int main(void)
{
    
    
	t=read();;
	while(t--)
	{
    
    
		n=read(); k=read();
		for(int i=1;i<=n;i++) a[i]=read();
		sort(a+1,a+n+1);
		printf("%d\n",a[k]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46527915/article/details/121822330