時間限制:1.00s | 記憶體限制:125.00mb
題目背景
替換永遠比刪除更徹底。題目描述
daniel13265 有一串由各種漂亮的貝殼組成的項鍊,但由於各種原因,這個項鍊不是環形的,而僅僅是用一根普通的絲線串起來的。項鍊上的每個貝殼都有乙個好看程度 ai,相同種類的貝殼有著相同的好看程度,而不同種類的貝殼有著不同的好看程度。
danie13265 定義, 第 l 個至第 r 個這一段貝殼是對稱的,當且僅當
∑ i=
lr(a
i−al
+r−i
)2=0
\sum_^r(a_i-a_)^2=0
i=l∑r
(ai
−al+
r−i
)2=0
daniel13265 經常從中取出一段貝殼。如果這一段貝殼是對稱的,他就會非常高興;如果這一段貝殼不是對稱的,那麼他會將其中的某些貝殼替換成新的,以使得這一段貝殼成為對稱的。一次替換可以任意地改變任何乙個位置上貝殼的好看程度,但是過多的替換會使這一段貝殼脫離原本的模樣,所以 daniel13265 至多會進行 k 次替換。如果一段貝殼在進行至多 k 次替換後能夠成為對稱的,那麼 daniel13265 就稱這一段貝殼是「可觀賞的」。
daniel13265 簡單地將第 l 個至第 r 個這一「可觀賞的」的貝殼段的「觀賞指數」定義為
∏ i=
lrai
\prod_^r a_i
i=l∏r
ai其中 ai 表示第 i 個貝殼原本的好看程度。
他現在很好奇,在這個貝殼組成的項鍊中,「可觀賞的」貝殼段中「觀賞指數」的最大值。但是由於這個值可能很大,所以你只需要求出它對 109+7 取模後的結果即可。
輸入格式
輸入共 2 行。輸出格式第一行兩個正整數 n,k,表示這個貝殼組成的項鍊中貝殼的數目與 daniel13265 對一段貝殼最多進行替換的次數。
第二行 n 個用單個空格隔開的正整數,第 i 個數 ai表示項鍊上第 i 個貝殼的好看程度。
輸出一行乙個非負整數,表示「可觀賞的」貝殼段中「觀賞指數」的最大值對 109+7 取模後的結果。輸入輸出樣例
輸入#1
7 1輸出#1輸入#21 2 4 2 3 3 4
6 1輸出#2說明/提示3 1 2 250000002 1 2
樣例解釋#1
「可觀賞的」貝殼段有 [1],[2],[3],[4],[1,2],[2,3],[2,4],[3,3],[3,4],[4,2],[1,2,4],[2,3,3],[2,4,2],[3,3,4],[4,2,3],[2,3,3,4],[4,2,3,3,4],其中「觀賞指數」最大的貝殼段為 [4,2,3,3,4]。樣例解釋#2
「可觀賞的」的貝殼段中「觀賞指數」最大的為 [2,250000002,1,2],其值為 109+8,對 109+7 取模後結果為 1。資料範圍
對於 100% 的資料,滿足 1 ≤ n ≤ 1000,0 ≤ k ≤ n,1 ≤ ai ≤ 109+7題意簡析
這道題,作為a題,題幹著實有點恐怖,簡直成了數學小作文閱讀理解,剛開始就勸退好多人(包括我)
(後來題面看了一輪,又回來了… )
咳咳,那麼這個題幹到底講了啥呢。in short:(寫到這裡突然尬住,到底講啥了呢(撓頭) )
①有一串由貝殼組成的項鍊(非環),每個貝殼有乙個「好看程度」,ai
②定義,l 至 r 段貝殼是對稱的,當且僅當(上面那個和式成立)我們小學二年級就學過:若平方項的和為0,則每一平方項均為0
即,ai==al+r-i,而 i 從 l 開始遞增,也就是說 l~r 段關於中軸對稱(物理上的對稱)
③一次替換可以改變任意貝殼的「好看程度」,假如一段貝殼經過 k 次替換後,是對稱的,則稱 l~r 這一段貝殼為「可觀賞的」(有種機翻的趕腳? )
④定義一段「可觀賞的」貝殼的「觀賞指數」為這一段貝殼「好看程度」的連乘積(上式)
⑤求表示「可觀賞的」貝殼段中「觀賞指數」的最大值對 109+7 取模後的結果注意:求「觀賞指數」時的ai是原本的ai,而非替換後的ai
實際上並未真正替換
注意:最大值的取模,而非取模的最大值
假·分析
這題寫著好累啊(咋這麼多字)
首先,乍一看雖然有點複雜,但好在n不是很大,思路也挺簡單:
雙重for迴圈,外層列舉區間長度len,內層列舉區間左端點 l,計算該區間是否能在k次替換內成為對稱的
如果能,則計算連乘積,並與最大值做取捨,複雜度o(n2),還是可以承受的。
然後你就會看到乙個又大又紅的wa(wa地一聲哭出來)
真·分析
「醉翁之意不在酒」啊,這出題人是真的黑
那麼一大坨題幹根本就不是重點,主要問題是這個資料範圍(1 ≤ ai ≤ 109+7)(1 ≤ n ≤ 1000)
要命了這可是連乘積啊,(109+7)1000,打個折109000,這可真是,玉皇大帝來了都沒轍
想啥呢,乘起來?桃子
所以作者說要模上109+7,但卻是先求最大值再取模,先取模會改變大小關係
也就是說,擺在我們面前的問題是:如何在不求值的情況下,比較兩個連乘積的大小
而且最大值無法用特定值表示,改用區間形式(int l, r)
此時,有兩種辦法:
①取對數
log10(a*b*…*z)==log10(a)+log10(b)+…+log10(z)
這時,109000 便轉化為9000,用double比較大小不在話下。
但是,有乙個問題,log10()函式計算效率不盡如人意,如果每次直接計算,勢必超時(血的教訓)
此時我們可以發現,計算存在冗餘,可以採用預處理出對數陣列的方式解決
②兩個連乘積中的每一項相除,拆分比較
例:a=a*b*c
b=d*e*f*g*h
t=(a/d)*(b*e)*(c/f)
while(t>=1)t/=g;…t/=h;
if(t>1)a>b;
實質上是比較a/b,做商,拆項可以防止溢位
兩種方法都是o(n)地掃瞄陣列,但除法比log更快,所以可以直接計算,無需預處理(這還真不好預處理),開了o2優化後時間大概在700ms左右,卡得死死的。不開就炸了。
當然我覺得第一種更好(200ms),(第二種是比賽時我的暴力美學…先寫上再說)
這裡採用取對數的方法(賽後補的一發)(更短一些)
"talk is cheap. show me the code."
#include
#include
typedef
long
long ll;
const
int maxn =
1e3+5;
const
int mod =
1e9+7;
int a[maxn]
;double log[maxn]
;struct node
;int
main
(void);
for(
int len =
1; len <= n; len++
)for
(int i =
1; i <= n - len +
1; i++)if
(cnt <= k);}
} ll res =1;
for(
int i = max.l; i <= max.r; i++
) res *
= a[i]
, res %
= mod;
printf
("%lld\n"
, res % mod)
;return0;
}
4 5 Daniel13265 的公開賽
4.5 daniel13265 的公開賽 題目鏈結 官方題解 戳這裡居然沒有官方 暴力做法 分奇偶形式的對稱數列,1e3資料 n2搞定,但是wa了 不知道為啥qwq include include include const int mod 1e9 7 using namespace std int...
洛谷大佬改編的
很久很久以前 演算法突然出現 帶來導論 帶走了智商又消失不見 程式設計十分危險 世間誰最勇敢 一位懵逼兒趕來 大聲喊 我要寫出最高的樹 打出最大的表 搜進最深的遞迴 把ac帶回到面前 老師非常高興 忙問他的技能 年輕人想了想 他說 老師我會 非確定性有窮狀態決策自動機 再來一次 非確定性有窮狀態決策...
題解 洛谷P1738 洛谷的資料夾
一 目錄概覽 二 題目大意 三 大致思路 四 實現 五 剖析 六 總結回顧 kkksc03想好了很多應該有的資料夾路徑名。問題是,需要是使這些資料夾都存在,需要新建幾個資料夾呢?資料夾路徑是什麼?例如 a b c,表示在根目錄下有a資料夾,在a資料夾裡有b資料夾,在b資料夾裡有c資料夾。其他路徑同理...