青藤编程营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;
}