训练赛题解

总结:

对于0基础的同学来说,前6题会做大部分就比较不错了,G题并不是难题,补题也需要会做,对于H、I,是针对有基础的同学出的题,0基础的同学没有学这2题的算法,可以自行学习或者暂时放弃这2题,确实比较有难度

A

本题签到,模拟即可

#include<bits/stdc++.h>
using namespace std;
string s;
int t;
void work(){
	cin>>s;int ans=0;
	for(int i=0;i<s.length();i++){
		if(s[i]<='9' && s[i]>='0') ans++;//判断数字

	}
	cout<<ans<<'\n';
}
int main()
{
	cin>>t;
	while(t--) work();
	return 0;
}

B

签到,高中应该都学过公式,或者使用循环

//code1
#include<bits/stdc++.h>
using namespace std;
long long a1,a2;
long long n;
 int main(){
     cin>>a1>>a2>>n;
       long long d=a2-a1;
       cout<<a1+(n-1)*d;
 } 
//code2
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int A1,A2,d,n;
	cin>>A1>>A2>>n;
	d=A2-A1;
	for(int i=2;i<=n;i++){
		A1+=d;
	}
	cout<<A1;
}

C

按题意模拟即可

//string
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
	while (getline(cin, s)) {
		int maxu = 0;
		for (int i = 0; i < s.length(); i++) {
			maxu = max(maxu, (int)s[i]);
		}
		for (int i = 0; i < s.length(); i++) {
			cout << s[i];
			if (s[i] == maxu)
				cout << "(max)";
		}
		cout << endl;
	}
}
//char
#include <stdio.h>
int main()
{
	char a[105];
	while (scanf("%s", a) != EOF) {
		int i;
		char max = a[0];
		for (i = 1; a[i] != '\0'; i++) {
			if (max < a[i]) 
				max = a[i];
		}
		for (i = 0; a[i] != '\0'; i++) {
			if (a[i] != max) 
				printf("%c", a[i]);
			else  
				printf("%c(max)", a[i]);
		}
		printf("\n");
	}
	return 0;
}

D

n n n年的牛,是前一年牛的头数,加上生下的头数,也就是能生产的母牛头数 ( n − 3 ) (n-3) (n3)

//递归写法
#include <iostream>
using namespace std;
int f(int n)
{
	if(n == 1)
		return 1;
	else if(n == 2)
		return 2;
	else if(n == 3)
		return 3;
	else return f(n-1) + f(n-3);
}
int main()
{
	int m;
	while (cin>>m) 
	{
		if (m == 0) break; 
		cout<<f(m)<<endl;
	}
	return 0;
}
//递推写法
#include <bits/stdc++.h>
#define maxn 100
using namespace std;
int n, f[maxn];
int main()
{
	f[0] = 1; f[1] = 1, f[2] = 2; f[3] = 3;
	for (int i = 4; i <= 60; i++) {//打表
		f[i] = f[i - 1] + f[i - 3];
	}
	while (1) {
		cin >> n;
		if (n == 0) break;
		cout << f[n] << '\n';
	}
}

E

这题卡空格,稍微有点恶心,需要处理一下行末空格否则会PE

输出杨辉三角,递推式:

f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i − 1 ] [ j − 1 ] f[i][j]=f[i-1][j]+f[i-1][j-1] f[i][j]=f[i1][j]+f[i1][j1]

#include <bits/stdc++.h>
using namespace std;
int n;
int tu[40][40];
int main()
{
	for (int i = 1; i <= 50; i++) {//初始化边界全1
		tu[i][1] = 1;
		tu[i][i] = 1;
	}
	for (int i = 2; i <= 40; i++)
		for (int j = 2; j < i; j++)
			tu[i][j] = tu[i - 1][j] + tu[i - 1][j - 1]; //递推式

	while (scanf("%d", &n) != EOF) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
				cout << tu[i][j];
				if (j != i) //最后不输出空格
					cout << " ";
			}
			cout << endl;
		}
		cout << endl;
	}
}

F

题意:

给定 T T T组数据,每组数据有一个输入为 N N N,输出第 N N N个不能被 3 3 3整除且末位不是 3 3 3的数。

因为 K < = 1000 K<=1000 K<=1000,枚举前1000个即可

#include <bits/stdc++.h>
using namespace std;
int t, k, cnt, a[100000];
bool check(int x)
{
	if (x % 3 == 0 || x % 10 == 3)
		return 0;
	else
		return 1;
}
int main()
{
	cin >> t;
	for (int i = 1; i <= 90000; i++) {
		if (check(i))
			a[++cnt] = i;
	}
	while (t--) {
		scanf("%d", &k);
		cout << a[k] << endl;
	}
}

G

题意:
给出一个只包含01的字符串,要求你将他分为若干个子串,使得每个子串中最小的未出现的数的和最小。

题解:

思维题

结论一:这个和最大为2,因为整个字符串只由0和1组成

  • 如果是若干个连续的1组成的子串,那么他产生的贡献为0。

  • 如果是若干个连续的0组成的子串,那么他产生的贡献为1。

  • 如果01混杂,那么产生的贡献为2

结论二:要把0和1分开来,连续0串的个数即为sum,且ans=min(2,sum)

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin>>t;
	while(t--){
		char s[100010];
		cin>>s+1;
		//输入s+1可以从1到n进行操作,比较方便,c写法:scanf("%s",s+1);

		int n=strlen(s+1);
		s[0]='1';//特判

		int ans=0;
		for(int i=1;i<=n;i++)
			if(s[i]=='0'&&s[i-1]=='1')
				ans++;
		cout<<(ans>2?2:ans)<<endl;
	}
    return 0;
}

H(二分)

题意:
一共有 n n n个英雄,他们要去屠龙,他们有力量值。一共有 m m m条龙,他有攻击力和防御力,当英雄们决定去杀这条龙时,只能派一人去屠龙,剩下的要守城。屠龙者的力量值要大于等于龙的防御力,剩下守城的人的力量值之和要大于等于龙的攻击力。通过1金币可以增加任意英雄的1点力量值。现求最少需要多少金币,才能杀某条龙(每次屠龙都是独立的过程,之前加的力量值不会累加到下一次屠龙)。
思路:
运用 l o w e r _ b o u n d ( ) lower\_bound() lower_bound()函数二分查找第一个力量值大于等于龙的防御力的英雄。

  • 如果不存在这个人,也就是龙的甲太高了,直接派最后一个人氪金和他干,剩下的人看情况要不要氪金买甲。

  • 如果这个人存在且至少存在一个人杀不动龙。那么就派他去屠龙,剩下的人去守城,但这样可能浪费很多屠龙者的力量值。因此我们再假设一种情况,让比他弱小一点点刚好杀不动龙的人去氪金屠龙,他留下来守城。比较这两种情况所需的金币数量。

  • 如果所有人都能屠龙,就让最弱的人去,也不好存在可能浪费很多力量值的情况了,因为只可能浪费更多。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
ll LINF = 1ll << 60;
int n, m, a[200010];
signed main()
{
	cin >> n;
	int sum = 0;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		sum += a[i];//求和
	}
	sort(a + 1, a + 1 + n);
	cin >> m;
	int x, y;
	for (int i = 1; i <= m; i++) {
		cin >> x >> y;
		int p = lower_bound(a + 1, a + 1 + n, x) - a;
		if (!a[p]) {//所有人都不能杀龙,派最大的氪金去
			cout << max((ll)0, y - (sum - a[n])) + x - a[n] << endl;
		}else  {
			int k1 = max(y - (sum - a[p]), (ll)0);//当前能屠龙的人

			int k2 = x - a[p - 1] + max(y - (sum - a[p - 1]), (ll)0);//上一个人氪金去       
			if (p == 1) k2 = LINF;//第一个人没有上一个人,特判                                          
			cout << min(k1, k2) << endl;
		}
	}
	return 0;
}

I(区间DP)

思路:

跑一遍区间DP,状态转移方程为

d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] + a [ i ] ∗ b [ j ] + a [ j ] ∗ b [ i ] − a [ i ] ∗ b [ i ] − a [ j ] ∗ b [ j ] dp[i][j]=dp[i+1][j−1]+a[i]∗b[j]+a[j]∗b[i]−a[i]∗b[i]−a[j]∗b[j] dp[i][j]=dp[i+1][j1]+a[i]b[j]+a[j]b[i]a[i]b[i]a[j]b[j]

把两端点换一下,找到最大值即可。

#include<bits/stdc++.h>
using namespace std;
const int N=5100;
typedef long long ll;
ll dp[N][N],a[N],b[N];
int main()
{
    int n,sum=0;
    cin>>n;
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)cin>>b[i];
    for(int i=1;i<=n;i++)sum+=(a[i]*b[i]);
    ll maxx=0;
    for(int len=2;len<=n;len++){
        for(int i=1;i+len-1<=n;i++){
            int j=i+len-1;
            dp[i][j]=dp[i+1][j-1]+a[i]*b[j]+a[j]*b[i]-a[i]*b[i]-a[j]*b[j];
            maxx=max(maxx,dp[i][j]);
        }
    }
    printf("%lld\n",sum+maxx);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值