1. 程式人生 > >2019.1.5 測試

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個數


完結!