把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

2019.1.5 测试

First Of All

这次考试其实总体来看还不是很难
然而做得并不好 只有第三题A了
主要是不会打高精&理解错了题意 (题意都读不懂还做什么题啊)


A 整数划分

Description

读入一个正整数n。要求将n写成若干个正整数之和,并且使这些正整数的乘积最
大。例如,n=13,则当n表示为4+3+3+3(或2+2+3+3+3)时,乘积=108为最大。

Input

一个整数,n。

Output

第1行输出一个整数,为最大乘积的位数。第2行输出最大乘积的前100位,如果
不足100位,则按实际位数输出最大乘积。(提示:在给定的范围内,最大乘积的
位数不超过5000位)。

Sample Input

13

Sample Output

3
108

分析

看到这道题的第一反应:并没有任何反应
5000位 高精度??? 均值不等式???(分成2个数) 算了 然后跳过

思路

首先比较容易想到的一个数学结论(并不会严谨证明 然而正确性显然)
打表找规律可以发现:
要使乘积最大,我们应该把它分成尽量多的3和2相乘 由于3和2一个是奇数,一个是偶数,所以这个数最后一定能完全地分成3和2的和
我们就把它一直分3出来 直到它小于等于4 我们就会发现一些情况:


原因:
由于4=2+2时最大 当这个数还剩下4的时候就不能再分3出来 因为4=1+3的情况并不够优秀 所以这种情况直接乘上n即可

还剩下3的时候:直接乘
还剩下2:直接乘
还剩下1:不存在 如果还剩下1,那它可以去找之前的一个2或者3 结合 然后使结果更优秀 事实上,由于我们之前一直都是分的3出来,唯一可能会出现1的情况就是最开始讨论的剩下4的情况,而它已经被我们解决掉了
还剩下0:这是一种什么奇怪的现象 由于我们每次-3 而最后的判断是小于等于4 所以不存在

结论:当这个数小于等于4的时候直接跳出循环把它自己乘上去就可以了


高精度部分

其实高精度乘法还是比较容易理解的 代码都比较好看 大概想一下平时手算竖式乘法的时候就可以理解了

主要是我实在是太久没有写过了
上一次写的高精度还是

在n年之前的生日qwq (我居然还会在生日写题)

代码

#include<cstdio>
#include<vector>
using namespace std;
#define MAXN 5005
int a[MAXN];
int n;
int main()
{
	int l=1,d=0,i;
	a[1]=1;
	scanf("%d",&n);
	while(n>4)
	{
		n-=3;
		for(i=1;i<=l;i++)
		{
			a[i]=a[i]*3+d;
			d=a[i]/10;//给下一位进的位
			a[i]=a[i]%10;
		}
		while(d>0)
		{
			a[i]=d%10;
			d=d/10;
			i++;
		}
		l=i-1;
	}
	for(i=1;i<=l;i++)
	{
		a[i]=a[i]*n+d;
		d=a[i]/10;
		a[i]=a[i]%10;
	}
	while(d>0)
	{
		a[i]=d%10;
		d=d/10;
		i++;
	}
	l=i-1;
	printf("%d\n",l);
	for(int i=l;i>=max(1,l-100+1);i--)
		printf("%d",a[i]);
	return 0;
}

B 地震

Description

(校内OJ)
农夫John的农场遭受了一场地震。有一些牛棚遭到了损坏,但幸运地,所有牛棚间的路经都还能使用。

FJ的农场有P个牛棚,编号1…P, C条双向路经连接这些牛棚,编号为1. . C。路经i连接牛棚ai和bi,路经可能连接ai到它自己,两个牛棚之间可能有多条路经。农庄在编号为1的牛棚.,

N头在不同牛棚的牛通过手机短信reroortj告诉FJ它们的牛棚(reportj)没有损坏,但是它们无法通过路经和没有损坏的牛棚回到到农场。当FJ接到所有短信之后,找出最小的不可能回到农庄的牛榭数目。这个数目包括损坏的牛棚。

讨论一下题意

果然语文还是太烂了
还想吐槽一下题目描述 有点绕 还有错别字qwq
我之前的理解:有N头奶牛的牛棚已知没有破坏,现在它们要回去,但是不能经过牛棚损坏的地方,请问这些奶牛最少有多少头奶牛不能回去(加上已经损坏的牛棚数目)

正确的理解应该是这样的 :

农夫John的农场遭受了一场地震。有一些牛棚遭到了损坏,但幸运地,所有牛棚间的路经都还能使用。

一共有P个牛棚,由C条双向路连接一条路可能连接相同的牛棚.农庄在编号为1的牛棚.

奶牛不能经过损坏的牛棚,并且只能沿道路行走。N头在不同牛棚的牛通过手机短信reroortj告诉FJ它们的牛棚(reportj)没有损坏,但是它们无法回到农场。找出最小的不可能回到农庄的牛棚数目。这个数目包括损坏的牛棚。

Input

第1行:三个空格分开的数:P, C,和N
第2 …C+1行:每行两个空格分开的数:ai和bi
第C+2 …C+N+1行:每行一个数:reroortj

Output

第1行:一个数,最少不能回到农庄的牛的数目(包括损坏的牛棚)

Sample Input

4 3 1
1 2
2 3
3 4
3

Sample Output

3

Hint

【数据范围】

1 ≤ P ≤ 30000,1 ≤ C ≤ 100000,1 ≤ N ≤ P,2 ≤ reportj ≤ P

分析

首先,样例没什么好说了的吧

3不能回去,那么一定是2损坏了 而2一旦损坏,2,3,4都不能回去

推广一下 一个牛棚不能到达1,一定是它去1的每一条路上都至少有一个点损坏

那么我们现在的问题就是 要让这些路径上的哪个点损坏 才能使更少的牛棚无法到达1

而显而易见的是:

那个损坏的点,离当前这个无法到达的点越远,就越有可能妨碍到更多的点

比如说这些比较极端的情况:

更极端的情况:

有了这个结论,我们就可以把那些被困住的点的邻接点视为破坏,然后从节点1开始搜索,搜到的点就是可以到达1的点,然后减去就可以了

C 最长上升子序列

Description

给出一个长度为N的整数序列,求出包含它的第K个元素的最长上升子序列。

Input

第一行两个整数N, K
第二行N个整数

Output

如题目所说的序列长度。

Sample Input

8 6
65 158 170 299 300 155 207 389

Sample Output

4

Hint

【数据范围】

0 < N ≤ 200000,0 < K ≤ N

分析

这道题比较简单
由于范围较大 我们可以考虑nlogn 的模板 (超链接)

于是问题开始变得简单起来,由于要保证第k个数存在 我们就将整个数列劈成两部分 求两个LIS 然后再夹上k 合起来
但是要注意的是:
左边那个LIS的最后面的那个数要比第k个数小,而右边的LIS的第一个数则要比它大(可以类比判断分段函数的单调性来理解)
(这个时候用nlogn算法的优势也体现出来了,可以更加方便地进行这项操作)
同时也要注意在进行右边的LIS更新时要先判断那个数大于第k个数


完结!

posted @ 2019-01-09 14:00  Starlight_Glimmer  阅读(7)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end