題目傳送門
給出乙個殘缺的字串,每個位置都 \(\in[0,9]\)。有 \(m\) 中貢獻,即 \(s,k\),表示該字串中沒出現一次 \(s\),貢獻便乘上 \(k\)。最後對貢獻求 \(c\) 次根,其中 \(c\) 是總出現次數。求貢獻的最大值。
字串長度以及貢獻字串長度之和 \(\le 1500\)
首先你需要想到我們可以全部取 \(\ln\),然後每次貢獻就是 \(+k\),求根就是 \(/c\),於是問題就是最大化:
\[\frac
\]然後你對這個二分,判斷條件就是:
\[\sum_>0
\]於是我們可以在 ac 自動機上進行dp,即設 \(f_\) 表示到第 \(i\) 個字串對應自動機上狀態j時的最大貢獻,轉移顯然。
於是,我們就可以在 \(nl\log w\) 的時間複雜度內解決這個問題。
#include using namespace std;
#define int register int
#define maxn 2005
template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}
template inline void read (t &t,args&... args)
template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,m;
int g[maxn][maxn][2];
double dp[maxn][maxn];
char s1[maxn],s2[maxn],ans[maxn];
struct auto
sum[now] ++,val[now] += v;
} void build ()
} } double work (double v)
}for (int i = 0;i <= cnt;++ i) val[i] += sum[i] * v;
int pos = 0;for (int i = 0;i <= cnt;++ i) if (dp[n][i] > dp[n][pos]) pos = i;
for (int i = n,now = pos;i;-- i) ans[i] = g[i][now][0] + '0',now = g[i][now][1];
return dp[n][pos];
}}t;
signed main()
t.build();
double l = 0,r = 1e9;
while (r - l > 1e-3)
t.work(l),printf ("%s",ans + 1);
return 0;
}
BJOI2019 奧術神杖
傳送門 首先w1w2 w3 w nn sqrt n nw1 w2 w3 wn 可以利用對數轉化 l og 2w1w 2w3 wnn 1n l og2w ilog 2 frac sum log 2 w i log2 n w1 w 2 w3 wn n 1 l og2 wi 那麼令ti log2 wi t...
BJOI2019 奧術神杖
傳送門 根據題意,需要知道神杖所包含了哪些咒語,大可使用自動ac自動機。關鍵是如何處理 sqrt c 這其實也很套路,一眼看過去,覺得根號這個東西顯然就不可做,於是想辦法消去根號。於是對於這個式子取對數,sqrt c frac magic v 1 v 2 v n 對於 frac 這種形式的答案,很顯...
BJOI2019 光線 遞推
題目鏈結 令 f i 表示光線第一次從第一塊玻璃射出第 i 塊玻璃的比率。令 g i 表示光線射回第 i 塊玻璃,再射出第 i 塊玻璃的比率。容易得到 beginf i f a i f b ig i g i b a i b b ig i a g a i a g b ig i end 對於 2 式,移...