青藤编程营Day6信心赛赛后总结

T1 藤藤的统计(count.cpp)

题目描述

计算在一个N*M的棋盘中共有多少个边长至少为1的正方形

输入文件

输入文件count.in仅有一行包含两个用空格隔开的整数N,M,表示棋盘大小。

输出文件

输出文件count.out仅有一行包含一个整数,表示共有多少正方形。

输入样例

2 2

输出样例

5

数据规模与约定

对于20%的数据,N ≤ 100,M ≤ 100。
对于50%的数据,N ≤ 1000,M ≤ 1000。
对于100%的数据,N ≤ 10000,M ≤ 10000。

思路

小学奥数题,通过公式循环即可直接输出答案

tip

数据定义使用long long,不然方格数会溢出

比赛代码(AC)

#include<bits/stdc++.h>
using namespace std;
long long n,m,s1;
int main(){
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=min(n,m);i++){
		s1+=(m-i+1)*(n-i+1);
	}
	cout<<s1;
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T2 藤藤的网络(net.cpp)

题目描述

放暑假了,小明想上网下载一些电影看,但是缓慢的网速令他无法忍受。他了
解到了接下来的N个小时中的网速情况,想找一段连续的M个小时来下载电影,并
且希望这M个小时的平均网速尽可能的大,你能编一个程序帮助他实现愿望吗?

输入文件

输入文件net.in第一行包含两个整数N、M,1<=M<=N<=1000000;第二行包含N个整
数,表示第N个小时的网速。相邻两数之间用空格隔开。

输出文件

输出文件net.out仅有一行包含一个实数,表示最大的平均网速,保留小数点后两位。

输入样例

6 3
3 6 1 5 6 4

输出样例

5.00

数据规模与约定

对于100%的数据,1 <=M<=N<= 1000000
对于40%的数据,1 <=M<=N<= 100

比赛思路

使用最大子段和求解,时间复杂度O((n-m)*n),超时60pts

订正思路

使用前缀和求连续m个数的和,时间复杂度O(n)

tip

1.此题仍需要使用long long定义,不然会溢出
2.此题因数据超过一百万,故需使用scanf和printf输入输出数据,不然会超时!!!

错因

1.使用O((n-m)*n)时间复杂度算法
2.未使用long long定义
3.未使用scanf和printf输入输出

比赛代码(40pts)

#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
int n,m;
int a[N],sum,ans;
int main(){
	freopen("net.in","r",stdin);
	freopen("net.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
//		a[i]=i;
	}
	for(int i=1;i<=n-m+1;i++){
		sum=0;
		for(int j=i;j<i+m;j++){
			sum+=a[j];
		}
		ans=max(ans,sum);
	}
//	cout<<ans;
	cout<<fixed<<setprecision(2)<<(ans*1.0)/(m/1.0);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

订正代码(AC)

#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
long long n,m;
long long a[N],sum[N],ans;
int main(){
	freopen("net.in","r",stdin);
	freopen("net.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		sum[i]=sum[i-1]+a[i];
//		a[i]=i;
	}
	for(int i=1;i<=n;i++){
		if(i+m<=n){
			ans=max(ans,sum[i+m]-sum[i]);
		}
	}
	printf("%0.2lf",(ans*1.0)/(m*1.0));
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T3 藤藤的箱子(boxes.cpp)

题目描述

藤藤有一堆箱子,每个箱子都有各自的长、宽、高。现在他想搭起一个很高
很高的“塔”,但是他又希望这个“塔”有较好的稳定性。于是,他希望放在下
面的箱子的长和宽都分别大于它上面的箱子的长和宽。现在他想知道他究竟能堆
出多高的塔。

又由于箱子是长方体的,因此你可以把它随意转动,也就是说,它的长、
宽、高是可以随意互换的。每种箱子的数量都可认为是无限个,当然,你不可能
全部用上。

你能帮助藤藤吗?

输入文件

第一行,一个整数n,表示箱子的数量。

接下来n行,每行三个整数,表示一个箱子的长、宽、高。

输出文件

一行,一个整数,表示可以堆起的最大高度。

输入样例

2
4 8 5
2 6 3

输出样例

18

样例解释

长方体表示为(长,宽,高);
则从下到上依次为(8,5,4),(5,4,8),(3,2,6)。

数据规模与约定

对于30%的数据,n<=10;
对于60%的数据,n<=30;
对于100%的数据,n<=100。

思路

将箱子的长宽高及它的变化存入结构体数组arr,arr从小到大排序,进行循环遍历,如果长宽均小于底部的箱子,则进行dp比较不叠和叠上去哪种更优,最后打擂台选出最优解

比赛代码(AC)

#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
	int a,b,c;
}arr[10010];
int ans,k;
int dp[10010];
bool cmp(node d,node e){
	return d.a<e.a||d.a==e.a&&d.b<e.b||d.a==e.a&&d.b==e.b&&d.c<e.c; 
}
int main(){
	freopen("boxes.in","r",stdin);
	freopen("boxes.out","w",stdout);
	cin>>n;
	while(n--){
		int x,y,z;
		cin>>x>>y>>z;
		arr[++k].a=x;arr[k].b=y;arr[k].c=z;
		arr[++k].a=x;arr[k].b=z;arr[k].c=y;
		arr[++k].a=y;arr[k].b=x;arr[k].c=z;
		arr[++k].a=y;arr[k].b=z;arr[k].c=x;
		arr[++k].a=z;arr[k].b=x;arr[k].c=y;
		arr[++k].a=z;arr[k].b=y;arr[k].c=x;
	}
	sort(arr+1,arr+k+1,cmp);
    for(int i=1;i<=k;i++){
        dp[i]=arr[i].c;
        for(int j=i;j>=1;j--){
        	if(arr[i].a>arr[j].a&&arr[i].b>arr[j].b){
            	dp[i]=max(dp[i],dp[j]+arr[i].c);
			}
		}
        ans=max(dp[i],ans);
    }
    cout<<ans;
    fclose(stdin);
    fclose(stdout);
	return 0;
}

T4 藤藤的字符串(str.cpp)

题目描述

藤藤喜欢把一个字符串打印n遍,请藤藤完成这个任务

输入文件

输入文件str.in第一行一个只包含小写字母的字符串

第二行一个正整数n,表示要把这个字符串打印n遍

输出文件

输出文件str.out一行,原字符串重复n遍的结果

输入样例

qingtengbc

3

输出样例

qingtengbcqingtengbcqingtengbc

数据范围

对于30%的数据,n<=10;

对于60%的数据,n<=30;

对于100%的数据,1<= n<=100。

保证原始字符串长度不超过100

思路

超级大水题,循环n次,输出字符串即可

比赛代码(AC)

#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int main(){
	freopen("str.in","r",stdin);
	freopen("str.out","w",stdout); 
	cin>>s>>n;
	for(int i=1;i<=n;i++){
		cout<<s;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T5 数字替换(change.cpp)

题目描述

藤藤很喜欢玩一个数字替换的游戏,给出一个n位正整数a,然后在给你一个长度为m数字序列b,你可以用b中的一些数字与a中的数位上的数字进行交换(当然也可以选择不交换),当然b中的每个位置上的数字最多只能被替换一次。这个游戏的目的是希望最终的a的数值最大。藤藤很聪明,在位数不多的情况下,总能快速的求出最后a的数值,但是当n很大时,藤藤就无能为力了,所以她希望会写程序的你帮助她快速的求解最大的a。

输入文件

输入文件change.in共三行。

第一行两个用空格隔开的正整数n,m。

第二行一个正整数a(a不含前导0)。

第三行一个长度为m的数字序列。

输出文件

输出文件change.out仅一行最大的 a 的数值(输出不能含前导 0)。

输入样例

1:

4 3

1024

010

2:

3 6

876

123459

输出样例

1:

1124

2:

976

数据规模与约定

对于20%的数据1≤n,m≤50

对于50%的数据1≤n,m≤2000

对于100%的数据1≤n,m≤100000

思路

存储b字符串中出现的数字个数,随后使用贪心思想,如数字还能用,且原数字小于该数字,则更改,并将次数--,最后输出更改的字符串a

比赛代码(0pts 爆零)

#include<bits/stdc++.h>
using namespace std;
int n,m,str[110];
string a,b; 
int main(){
	freopen("change.in","r",stdin);
	freopen("change.out","w",stdout);
    cin>>n>>m>>a>>b;
    for(int i=0;i<m;i++){
        str[b[i]-'0']++;
    }
    for(int i=0;i<n;i++){
        for(int j=9;j>=0;j--){
            if(a[i]<(j+'0')&&str[j]==1){//以为只能改一次而爆零
                a[i]=(j+'0');
                str[j]--;
                break;
            }
        }
    }
    cout<<a;
    fclose(stdin);
    fclose(stdout);
	return 0;
}

订正代码(AC)

#include<bits/stdc++.h>
using namespace std;
int n,m,str[110];
string a,b; 
int main(){
	freopen("change.in","r",stdin);
	freopen("change.out","w",stdout);
    cin>>n>>m>>a>>b;
    for(int i=0;i<m;i++){
        str[b[i]-'0']++;
    }
    for(int i=0;i<n;i++){
        for(int j=9;j>=0;j--){
            if(a[i]<(j+'0')&&str[j]>=1){
                a[i]=(j+'0');
                str[j]--;
                break;
            }
        }
    }
    cout<<a;
    fclose(stdin);
    fclose(stdout);
	return 0;
}
posted @ 2020-08-21 20:41  小罐猹  阅读(332)  评论(0编辑  收藏  举报