2019 1 5考試題解

2022-09-18 04:00:36 字數 4161 閱讀 9675

題目描述

讀入乙個正整數n。要求將n寫成若干個正整數之和,並且使這些正整數的乘積最大。例如,n=13,則當n表示為4+3+3+3(或2+2+3+3+3)時,乘積=108為最大。

輸入

乙個整數,n。

輸出

樣例輸入

13
樣例輸出

3

108

資料範圍10 ≤ n ≤ 31000

首先確定一點,這道題是需要用高精的,=-=估計看得一些人頭疼,畢竟高精這種東西有些難弄。乙個還好,如果要寫多個高精那簡直令人崩潰。

我們首先就要確定方法。其實看著這道題我們可以想到乙個非常簡單的dp(沒想到吧,這種題還能用dp)

夠簡單吧。。。但這裡需要弄一下初值,也就是dp[2] = 2 , dp[3] = 3。為什麼要這樣弄呢?我們發現如果用其他的數湊成2,dp[2]的最大值只能是1,但這樣還不如用它本身來的划算。

這乙個dp有兩個變數,以這樣的資料範圍,列舉直接爆了。考試的時候,我就用的這乙個方法,我們就必須找更多的性質,於是,打一下表

i = 1

dp[i] = 1

i = 2

dp[i] = 2 (1)

i = 3

dp[i] = 3 (2)

i = 4

dp[i] = 4

i = 5

dp[i] = 6

i = 6

dp[i] = 9

i = 7

dp[i] = 12

i = 8

dp[i] = 18

i = 9

dp[i] = 27

i = 10

dp[i] = 54

看起來並沒有什麼規律。。。但我們看看,除了2,3,其餘的dp值都比i的值大,然而看看其他的dp值,誒。。。好像正是2與3組合所成。。的確,那麼我們僅僅需要將n分成由2與3組成的部分就可求出最優了。後面的所有dp值,本質上都是2與3所湊。從5開始,所有的dp值都比i大了。

那肯定2與3也要優先選乙個先累計啊,我們又需要進行討論,我們找比較特殊的點6.

可以知道6可以分成(2,2,2)或者(3,3)。很明顯,後者更優。那麼我們就可以知道,乙個數如果分出來2的個數大於等於3,我們是可以將它們3個一對轉換成2個3的。那麼2的個數我們就控制在了2個以內。所以,這道題就是優先分3

乙個特殊點:到了4,肯定分2個2,不是3與1。

那麼這道題也僅僅需要高精乘,**並不難。

#include#include#include#include#include#include#includeusing namespace std;

int n , a[100005] , c[5005];

inline void cheng(int x)

c[0] = i;

while (c[c[0]] == 0 && c[0] > 1)

c[0] --;

}int main()

for (i = 1;i <= tot ;i ++)

cheng(3);

if (tot1)

cheng(tot1);

printf("%d\n",c[0]);

for (i = c[0] ;i >= max (c[0] - 99 ,1) ; i --)

printf("%d",c[i]);

}

事實證明思路還是多去實現,這樣就一步一步可能就可以找到更好的方法,打出正解。對於基本性質,要能看出來對於我來說還是有些困難。

題目描述

農夫john的農場遭受了一場**。有一些牛棚遭到了損壞,但幸運地,所有牛棚

間的路經都還能使用。fj的農場有p個牛棚,編號1..p,  c條雙向路經連線這些牛

棚,編號為1. . c。路經i連線牛棚ai和bi,路經可能連線ai到它自己,兩個牛棚之

間可能有多條路經。農莊在編號為1的牛棚.,n頭在不同牛棚的牛通過手機簡訊

reroortj告訴fj它們的牛棚(reportj)沒有損壞,但是它們無法通過路經和沒有損壞

的牛棚回到到農場。當fj接到所有簡訊之後,找出最小的不可能回到農莊的牛榭

數目。這個數目包括損壞的牛棚。

輸入

第1行:三個空格分開的數:p, c,和n

第2 ...c+1行:每行兩個空格分開的數:ai和bi

第c+2 ...c+n+1行:每行乙個數:reportj

輸出

第1行:乙個數,最少不能回到農莊的牛的數目(包括損壞的牛棚)

樣例輸入

4 3 1

1 22 3

3 43

樣例輸出

3
有些人可能不理解題意,其實可以這樣理解,reportj就表示它不能夠回到1,那麼為啥它不能回到1呢?那麼肯定它能夠到1的某個必經之點是有問題的(要麼破損,要麼不能夠回到1),由於我們要求的是最小值,我們盡量要讓這個有問題的必經之點最優。

我們肯定令這乙個點周圍與它直接相連的點有問題即可。其實也很好看出來,如果說,你走了很遠(中途經歷了很多的點),這個時候你才令下乙個必走的點斷掉,那麼前面走過的那些點都到不了1了。因為如果前面走過的點少了斷掉的這一點還能到1,那麼不能到1的那個點依舊可以到1,不合題意還要刪除點。那豈不是很慘。違背了最優性,因此我們控制一下,盡量將範圍鎖定在打**的這乙個點的周圍。於是,僅僅將與它直接相連的點刪除標記即可。

本校大佬的圖例(其實是題解,表示我不想畫圖)

暴力出奇蹟,標記了點,dfs從1開始看哪些點能遍歷到吧。最後統計就行了。

#include#include#include#include#include#include#include#define p 30005

using namespace std;

int p , c , n , ans;

int mov[p];

vectorg[p];

void dfs(int x)

}}int main()

for (int i = 1 ;i <= n ;i ++)" class="mathcode" src=""/>

的時間複雜度。做這道題,必須掌握高階的演算法。

的確,最長上公升子串行是可以利用二分在

的時間複雜度下完成。

欲知如何做,可以看看一道求最長不下降序列的題。

知道了優化方法,這道題可以說是輕鬆很多了,很多方式都可以解決,這裡列舉一下

1到k求乙個最長上公升。n到k求乙個最長下降,當放入k的時候,就得到了序列的長度。最後相加-1即可。

去掉1到k中小於a[k]的數,然後1到n求最長上公升子串行。

從1到k-1中求乙個最長上公升,比a[k]大的數就不處理,從k + 1到n求乙個最長上公升,同樣,比a[k]小的就不管。

主要的思路方法還是差不多。考的演算法也很單一。

這裡的二分可以用lower_bound來運算,但我不經常使用,這個函式是比較方便的。

#include#include#include#include#include#include#include#define n 200005

using namespace std;

int n , k , a[n] , dp[n] , len , ans;

int main()

for (int i = 1 ;i <= n ;i ++)

} printf("%d",len);

}

考試的時候莫名錯了,感到很奇怪,然而事後一打,一遍過,這就讓我感到疑惑了,我考試的時候到底是**寫得有問題呢?反正問題是有的,看起來又是很簡單的細節問題,以後還是要注意一下,這種失分真的得不償失啊。

沒有太大的問題,關鍵還是細節,這可以說是十分重要的。時間我覺得還是比較充裕的,打完**後還是有一段不少的時間,然而**的質量其實不算太高。發現考試打的**都好複雜,事後再來做發現輕鬆多了。這便也說明了考試還真是考察綜合能力,不僅僅只有程式設計,所以啊,只有經過多次的考試,才可能夠在考場真正發揮自我的能力。

考試題題解

主講人igl albl 試題t2 t3 t1 t4 t5 暴力 dfs所有路徑,在使用clock的情況下預計 text 題意 給你一張有向圖,距離為 text 的正整數次冪的兩點間可以重新連一條長為 text 邊,求在此情況下的從起點到終點最短路。我們用 text 表示點 text 到點 text ...

考試題解集合

某天忽然發現自己的blog裡全是考試題解 那麼為什麼不鏈到一篇blog裡呢?避免首頁全是加密blog看起來不大友善,大概也會整齊一點。估計是個大工程但還是作死地開始啦。有些難題是單獨寫的,就不鏈了。密碼仍然是開機使用者名稱 入學年份 兩個班級,希望總是能比過去的自己更用心!2018 4月 14 17...

2020 11 25 考試題解

題目描述 有一圈數,其數目為n個,定義一次操作為每個數變為原數圈中的自己與相鄰的兩個數這三個數的異或和,給出原陣列和操作次數,請算出最後的結果陣列。輸入資料 輸入第一行包含兩個正整數n和k,分別表示陣列數目和操作次數。第二行 n 個整數。輸出資料 僅包含一行n個整數。樣例輸入 3 1 1 2 3樣例...