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