CQOI 2016 偽光滑數

2022-05-08 04:51:12 字數 1171 閱讀 1464

又是一道神仙題。蒟蒻表示不看題解根本不會做

首先我們定義乙個 dp 陣列 \(\mathtt\) 表示:最大質因子為 \(\mathtt\),分解成 j 個質數(可以相同)組成的集合(其中 \(\mathtt\) 是這個集合的根節點,在這裡我們用左偏樹)。我們知道,只要得到了這個 dp,我們就可以把這個玩意兒的權值塞進佇列排序,再插入兒子進行查詢。

為了求得這個陣列,我們需要再定義乙個 \(\mathtt\) 表示:最大質因子的編號小於等於 i,分解成 j 個質數(可以相同)的集合。

那麼就有:

\[\mathtt

\]然後 f 陣列就可以這樣得到:

\[\mathtt^g[i-1][j-k]*p[i]^k}

\]由於 dp 的特殊性,我們不能直接在左偏樹上修改,所以要建可持久化左偏樹。

其中加法是左偏樹的合併,乘法是在權值上乘上乙個數。

最後解釋一下:我們的權值其實就是所求的 m。\(\mathtt\) 的兒子其實就是乘乙個 \(\mathtt\) 就能滿足成為最大質因子為 \(\mathtt\),有 j 個質數的 m,只不過沒有 \(\mathtt\) 大而已。我們把每個 \(\mathtt\) 設為 \(\mathtt\) 標記,將懶標記乙個個乘下去再用左偏樹維護仍然保證成為最大質因子為 \(\mathtt\),有 j 個質數的 m。

#include #include #include using namespace std;

typedef long long ll;

const int n = 17000005;

ll n;

int cnt, p[130], siz, k, f[130][130], g[130][130];

bool vis[130];

priority_queue < pair < ll, pair > > q;

ll read()

return x * f;

}void prime()

}}struct lt

void pushdown(const int o)

int unite(int o, int y)

void init() }}

void solve()

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

}}t;int main()

CQOI2016 偽光滑數

題目描述 若乙個大於1的整數m的質因數分解有k項,其最大的質因子為ak,並且滿足ak k n,ak 128,我們就稱整數m為n 偽 光滑數。現在給出n,求所有整數中,第k大的n 偽光滑數。題解 題面的k意思是將這個數質因數分解後所有的質因子的指數和。我們先把128以內的所有素數找出來,然後做乙個dp...

4524 Cqoi2016 偽光滑數

time limit 10 sec memory limit 512 mb submit 280 solved 133 submit status discuss 若乙個大於r的整數j的質因數分解有f項,其最大的質因子為ak,並且滿足ak k n,ak 128,我們就稱整數j為n 偽光滑數。現在給出...

bzoj 4524 Cqoi2016 偽光滑數

看到求第k大,k很小,首先應該想到k路歸併。利用可持久化可並堆進行dp g i j 表示前i個素數,用了j個質因子可以表示的數的集合 g i j sigma g i 1 j k p i k sigma表示集合的並,乘法用打標記實現。然後k路歸併,按照使用了的質因子個數分類。令mx j 表示取j個質因...