2023/2/11 蓝桥备战acwing刷题(枚举、简单枚举、水题、map题,中等的枚举)

4261. 孤独的照片

给一个长度为N的字符串,字符串内容为G或H,求长度大于等于3且只含一个H或G的子串个数
我的思路是两次遍历找单独g和单独h的左右两边,但是代码实现很麻烦
y总的还是牛啊,统计左右两边就正向逆向两次遍历,用两个数组存储当前位置左右两边的G和H个数
有个小track,如果不是0就取两数之差,可以max(0,a-b)

#include<iostream>
#include<vector>
using namespace std;

const int maxx = 5e5+1;

int l[maxx],r[maxx];

int main(){
	int N;
	cin>>N;
	string s;
	cin>>s;
	
	//先看左边的
	for(int i=0,h=0,g=0;i<N;i++){
		if(s[i]=='G'){
			l[i]=h;
			h=0;
			g++;
		}else{
			l[i]=g;
			g=0;
			h++;
		}
	}
	//再看右边的(逆序来一次)
	for(int i=N-1,h=0,g=0;i>=0;i--){
		if(s[i]=='G'){
			r[i]=h;
			h=0;
			g++;
		}else{
			r[i]=g;
			g=0;
			h++;
		}
	}
	long long res = 0;
	//统计
	for(int i=0;i<N;i++){
		res+=(long long)l[i]*(long long)r[i]+max(0,l[i]-1)+max(0,r[i]-1);
	}
	cout<<res<<endl;
	return 0;
}

3400统计次数

题目吓人,结果看了下是简单题
强行遍历和枚举,顶多达到O(6*1e6)

#include<iostream>
#include<vector>
using namespace std;

int main(){
	int n,k;
	cin>>n>>k;
	int res = 0;
	for(int i=1;i<=n;i++){
		int tmp = i;
		while(tmp){
			int mo = tmp%10;
			tmp/=10;
			if(mo==k){
				res++;
			}
		}
	}
	cout<<res<<endl;
	return 0;
}

3443学分绩点

c语言入门题

#include<iostream>
using namespace std;

double jidian(int g){
    if(g>=90){
        return 4.0;
    }else if(g>=85){
        return 3.7;
    }else if(g>=82){
        return 3.3;
    }else if(g>=78){
        return 3.0;
    }else if(g>=75){
        return 2.7;
    }else if(g>=72){
        return 2.3;
    }else if(g>=68){
        return 2.0;
    }else if(g>=64){
        return 1.5;
    }else if(g>=60){
        return 1.0;
    }else return 0;
}

int xuefen[11];

int main(){
    int N;
    cin>>N;
    int xuefensum = 0;
    for(int i=0;i<N;i++){
        cin>>xuefen[i];
        xuefensum+=xuefen[i];
    }
    double jidiansum = 0;
    for(int i=0;i<N;i++){
        int grade;
        cin>>grade;
        jidiansum+= jidian(grade)*xuefen[i];
    }
    printf("%.2lf\n",jidiansum/xuefensum);
    return 0;
}

4818奶牛大学

用map进行分组并排序,然后从高价开始遍历
这里注意一下 map的反向查找

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxx =1e5;
typedef long long ll;
const ll maxxx=1e12;

int main(){
    int N;
    map<int,int> m;
    cin>>N;
    for(int i=0;i<N;i++){
    	int tmp;
    	cin>>tmp;
    	m[tmp]++;
    }
    ll resTotal = -1;
    int resPrice;
    int prePerson=0;
    for(auto it = m.rbegin();it!=m.rend();it++){
    	int curPerson = prePerson+it->second;
    	ll tmpTotal = (ll)it->first*(ll)curPerson;
    	prePerson=curPerson;
    	if(tmpTotal>=resTotal){
    		resTotal=tmpTotal;
    		resPrice=it->first;
    	}

    }
    cout<<resTotal<<" "<<resPrice<<endl;
    return 0;
}

4366上课睡觉

先明确总石子数sum是堆数cnt的个数,然后不知道怎么知道的一个数n有log(n)个约数
然后通过类似尺取的方法从左往右遍历各堆看是否都能凑成sum/cnt个石子
故时间复杂度为O(nlogn)

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxx = 1e5+1;

int arr[maxx];


bool check(int num,int N){
	int tmpSum=0;
	for(int i=0;i<N;i++){
		tmpSum = tmpSum+arr[i];
		if(tmpSum>num){
			return false;
		}else if(tmpSum==num){
			tmpSum=0;
		}
	}
	return true;
}


int main(){
	int T;
	cin>>T;
	while(T--){
		memset(arr,0,sizeof arr);
		int N;
		cin>>N;
		int sum=0;
		int pre = -1;
		for(int i=0;i<N;i++){
			cin>>arr[i];
			sum+=arr[i];
		}
		if(sum==0){cout<<0<<endl;continue;}
		//求可能的堆数
		for(int i=sum;i>=1;i--){
			if(sum%i==0){
				bool res = check(sum/i,N);
				if(res){cout<<N-i<<endl;break;}
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值