日常摸魚 牛客挑戰賽3

2022-05-15 18:49:55 字數 1555 閱讀 6896

期望dp,要用字首和優化一下。。略了

比較水的追及問題。。。但是兩個點一開始就在一起要特判掉。

稍微轉化一下。。只用求數列中任意兩對數的和的位數,這個可以隨便套資料結構。

思路大致跟上一場蝴蝶差不多。。而且比上場那個簡單多了,連資料結構都不用套。。

給定乙個n個點的樹,以1為根,邊權都是1。乙個人從起點s開始隨機遊走(每一步等概率沿當前點的某一條邊走),目的地是根節點。你可以選擇k個點做標記,使得人在有標記的點時,他下一步一定向根節點方向的邊走一步,並且再也不會回到有標記的點。在最優的標記方案下,人期望多少步能到根節點。

\(n\leq 100000,k\leq 50\)

首先樹上的隨機遊走的結論:從\(i\)到\(fa_i\)的期望步數為\(2size_i-1\)。記\(f_i\)

\(=\)

\(2size_i-1\)

然後如果沒有標記的話,答案就是i到根節點所有的期望加起來。

有標記的情況下,這些標記顯然打在i到1的路徑上。

我們把這條路徑從起點到根提取出來,這就變成乙個序列(1號點是起點,最後乙個點是根)上的dp問題。

式子:\(f_\)

\(=\)

\(min(f_+1+sum_i-sum_j-2sz_j(i-j))\)

\(f_\) 表示前i個點放了k個標記的答案。

\(sum_i\)表示前i個點的\(f_i\)之和。

\(sz_j\)表示第i個點在原樹中的\(size\)值

這個式子的形式明顯可以斜率優化。

#include #define ll long long

#define ld long double

using namespace std;

const int n=1e5+10;

int read()

while(ch>='0'&&ch<='9')

return x*f;

}void print(ll x)

int n,m,k,st;

vectorr[n];

int fa[n];

int sz[n];

void dfs(int x)

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

while(ch>='0'&&ch<='9')

return x*f;

}void print(ll x)

void pls(ll &x,ll y)

int n;

int a[n];

ll len[n][n],num[n][n],cnt[n][n],dp[n][n];

int main()

else

}if(a[i+1]!=0)}}

ll ans=0;

for(int i=0;i<=n;++i) pls(ans,dp[n][i]);

ans=(ans%p+p)%p;

for(int i=1;i<=tt;++i) pls(ans,ans);

printf("%lld\n",ans);

return 0;

}

牛客挑戰賽58

前i 1的二進位制相等,a的前n個數的前i 1位可以亂取,b的前n 1個數前i 1位也可以亂取,因為b的第n個數的前i 1異或可為任意值,所以sum1 2 i 1 n 2 i 1 n 1 2 i 1 2n 1 a的第i位為1且b的第i位為0 只要a的n數第i位中有乙個不為0的,a的第i位不為0,b的...

牛客Wannafly挑戰賽12 題解

傳送門 說是比賽題解,其實我只會前三題 後面的一定補 t1題意,在乙個長度為n的時間內,問如何選擇存款期限,使得收益最大。dp include include include include using namespace std define fi first define se second d...

牛客挑戰賽 56 D

給出乙個排列 p 求滿足條件的三元組 i,j,k 個數 n le 10 5 莫比烏斯反演 感覺大半年沒有複習過莫比烏斯反演了,於是這個題直接幫我複習了一下 真 訓練 考慮固定 j 計算貢獻,然後就是求字首和字尾中 gcd p i,x k 的個數了,記出現之前每個數出現次數為 cnt 那麼貢獻為 be...