7.28PTA热身赛题解

链接:qaq

1.

现有三种操作:“从键盘输入一个字符”、“复制当前所有内容到剪贴板”、“读取剪贴板内容并粘贴到尾部”(初始状态下剪贴板为空)
你每次可以选择上述一种操作执行,试问最多操作N次时最多可以生成多长的内容?

输入格式:

包含多组输入,每组在一行中给出最多操作次数N,1≤N≤50。

输出格式:

对每一组输入,在一行中输出限定条件下最长内容的长度。(题目保证数据均在int范围内)

输入样例:

注意为多组输入

5
6

输出样例:

6
9


样例解释:
打字->打字->打字->复制->粘贴->粘贴,共6步操作产生了9位的内容。

 

以我蒟蒻的眼光来看,是找规律的。

开始的时候是只有这一组测试样例,往下推的时候,数算错了,导致wa了。后来中场的时候,出题人给加了1~10的 样例,就呃呃呃。上代码。另外,这题写法贼多。

#include <stdio.h>
int main()
{
	int n;
	int dp[51]={1,2,3,4,6,9,12,18,27,36,54,81,108};
	int cnt=0;int j=3;int t=6;
	for(int i=5;i<51;i++)
	{
		
		if((i-1)%3!=0)
		{
			dp[i]=dp[i-1]+j;
			cnt++;
			if(cnt==2)
			{
				j=j*3;
				cnt=0;
			}
		}	
		
		
		if((i-1)%3==0)
		{
			dp[i]=dp[i-1]+t;
			t=t*3;
		}
	}
	
/*	for(int i=0;i<51;i++)
	{
		printf("%d\n",dp[i]);
	}
	*/
	while(~scanf("%d",&n))
	{
		printf("%d\n",dp[n-1]);
	}
	return 0;
}

2.

题目1.png

  • 给出一系列由“ODGBLqShEZI”中的字母组成的单词,如图所示,每个字母翻转后的数字可以看作是该字母的分值,现在你需要选择其中的一些单词构成一篇作文,作文的得分则是从右向左依次读取每个字母所对应的分值,例如由“ODGBLq”和“ZI”组成的一篇作文“ZIODGBLq”,得分为67890012。
  • 题目会给出作文最长长度。
  • 所给出的每个单词最多可使用一次(若有重复的单词,每个单词可使用一次),单词不可截断使用。
  • 作文的得分不能包含前导零,但是可以添加小数点作为小数,如作文“BLOOD”得分为0.0078而不是78

输入格式:

第一行为作文的长度限制L,1≤L≤200;
第二行为所给出的单词数N,1≤N≤10000;
接下来的N行,每行给出一个单词,保证由“ODGBLqShEZI”中的字母组成且不会出现全为O/D的情况;
单词的长度不超过32

输出格式:

输出最大得分;

输入样例:

10
5
GDO
BSh
EGSEOq
L
SBL

输出样例:

样例解释:选取“EGSEOq”、“L”、“SBL”,对应分数分别为(395306、7、587)
拼接并反向后得到的7857603593当作一个整体(整数)作为该作文的得分

7857603593

这一题吧,当时没怎么看。其实就是把字符串连起来以后排序,排完以后就是一个01背包问题。注意的点在代码里都备注了。

#include <stdio.h>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100005;
string dp[maxn];

int cmp(string a,string b)
{
	return a+b>b+a;   //一定不能return a>b  因为要先拼在一起!!!!
}

int main()
{
	int L,n;
	string str;
	map<char,string> M;
	M['O']="0";
	M['D']="0";	
	M['I']="1";	
	M['Z']="2";	
	M['E']="3";
	M['h']="4";
	M['S']="5";	
	M['q']="6";
	M['L']="7";	
	M['B']="8";
	M['G']="9";
	
	scanf("%d %d",&L,&n);
	int len[maxn];
	string tt[maxn];
	for(int i=0;i<n;i++)
	{
		cin>>str;
		
		for(int j=str.length()-1;j>=0;j--)
		{
			tt[i]+=M[str[j]];	
		}
	}
    
    //len[i]=tt[i].length();   //这里会wa死 因为在sort以前 len和tt是一一对应的 排完就不是了
	//所以需要排完以后再搞len  建议直接上结构体!! 
	sort(tt,tt+n,cmp);
	
	for(int i=0;i<n;i++)
	{
		len[i]=tt[i].length();
	} 
	for(int i=0;i<n;i++)
	{
		for(int j=L;j>=len[i];j--)
		{
			dp[j]=max(dp[j],dp[j-len[i]]+tt[i]);
		}
	}
	
	if(dp[L][0]=='0')
	{
		printf("0."); 
	}	
	else
	cout<<dp[L][0];
	
	for(int i=1;i<L;i++)
	{			
		cout<<dp[L][i]; 
	} 	
	printf("\n");
	return 0;
}

3.

给出由n个非负整数组成的数组,接下来有n次操作,每次给出一个介于1和n之间的数k,摧毁在初始数组中的第k个数。
每次操作后需要找到数字和最大的连续子序列(中间有被摧毁数则为不连续),并输出该序列内的数字之和
提示:离线处理更方便

输入格式:

第一行给出数组的长度n;1≤n≤100 000
第二行包含n个以空格分隔的非负整数,为数组内元素;(每个数字值位于[0,1e9])
第三行包含n个以空格分隔的正整数,表示摧毁在初始数组中的第几个数。

输出格式:

打印共N行,每一行输出一个整数,摧毁元素后最大子序列元素和为多少。

输入样例1:

在这里给出一组输入。例如:

4
1 3 2 5
3 4 1 2

输出样例1:

在这里给出相应的输出。例如:

5
4
3
0

输入样例2:

在这里给出一组输入。例如:

5
1 2 3 4 5
4 2 3 5 1

输出样例2:

在这里给出相应的输出。例如:

6
5
5
1
0

输入样例3:

在这里给出一组输入。例如:

8
5 5 4 4 6 6 5 5
5 2 8 7 1 3 4 6

输出样例3:

18
16
11
8
8
6
6
0

在这里给出相应的输出。例如:

 

当时是用dp写的,可怜我这个憨憨超时,想到应该可以用线段树,但对于这个题用线段树比较麻烦(其实是我不会)。

后来知道了一种很神奇的写法,就是把摧毁反着看,当成是建立,然后用并查集写。这样的话,一个区间正好在一个集合里,但我搞了很久,主要是太菜了,并查集不是很理解。。

#include <stdio.h>
#include <algorithm>
using namespace std;

int n,k;
int fa[100001];
int ans[100001];
int a[100001];
int b[100001]; 
int vis[100001]={0};
int value[100001];
int init()
{
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
}

int findd(int root)
{
	if(fa[root]!=root)
	{
		fa[root]=findd(fa[root]);
	}
	return fa[root];
}

void unionn(int x,int y)
{
	int p1=findd(x);
	int p2=findd(y);
	
	if(p1!=p2)
	{
		fa[p1]=p2;
		value[p2]+=value[p1];
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&value[i]);
	}
	for(int i=1;i<=n;i++)  //坐标 
	{
		scanf("%d",&b[i]);
	}
	
	init();
	
	int maxx=0;
	for(int i=n;i>=1;i--)
	{
		ans[i]=maxx;
		vis[b[i]]=1;
		if(vis[b[i]-1]==0&&vis[b[i]+1]==0)
		{
			maxx=max(maxx,value[b[i]]);
		}
		if(vis[b[i]-1]==1)
		{
			unionn(b[i]-1,b[i]);
			maxx=max(maxx,value[findd(b[i]-1)]);
		}
		if(vis[b[i]+1]==1)
		{
			unionn(b[i],b[i]+1);
			maxx=max(maxx,value[findd(b[i]+1)]);
		}	
	}

	for(int i=1;i<=n;i++)
	{
		printf("%d\n",ans[i]);
	}
	return 0;
}	

眼泪湿润了我的身体,农民伯伯把我摆在市场上都不用浇水,路过的叔叔阿姨都纷纷感叹:“好菜啊,真的是好菜啊。”

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页