題目大意:
給你乙個序列a1,
...,
an
a_1,...,a_n
a1,..
.,an
.讓你從裡面選出乙個子集s
ss,使得子集中任意兩個數都互為倍數.求最大子集.(n≤1
e5,a
i≤1e
7n \leq 1e5,a_i\leq1e7
n≤1e5,
ai≤
1e7).
題目思路:
首先,本題的弱化版:
整除關係具有傳遞性,所以任意兩個數成倍數關係不妨轉化為:【對子集s
ss排序後相鄰兩個數成倍數關係。】
那麼有乙個很自然的類似lis的o(n
2)
o(n^2)
o(n2
)填表法.見弱化版。
這裡考慮刷表法,令dp(
i)
dp(i)
dp(i
)代表子集中都以i為約數的最大子集.然後用dp(
i)
dp(i)
dp(i
)更新所有i
ii的倍數的dpdp
dp值。根據自然數的倒數的級數定理,該方法的複雜度為:o(w
logw
)o(wlogw)
o(wlog
w)進一步優化:只用素數的倍數去更新.
因為乙個合數可以由多個素數組成。
例如: 從dp(
2)
dp(2)
dp(2
) 轉移到 dp(
12)
dp(12)
dp(12)
.要乘上6.而 6=2
∗3
6 = 2 * 3
6=2∗3.
那麼用前者的方法我們可以一步從dp(
2)
dp(2)
dp(2)到dp(
12)
dp(12)
dp(12)
.用後者的方法是從dp(
2)
dp(2)
dp(2)到dp(
6)
dp(6)
dp(6
)再到dp(
12)
dp(12)
dp(12)
//或者從2到4到12.
所以後者少了很多次無用的轉移.具體的,根據素數的倒數的級數定理,該方法的複雜度為:o(w
logl
ogw)
o(wloglogw)
o(wlog
logw
) ac**:
#include
using
namespace std;
const
int maxn =
1e7+5;
int dp[maxn]
, sz[maxn]
;int prime[maxn]
, cnt;
bool book[maxn]
;void
init()
}}intmain()
int ans =0;
int up =
1e7;
for(
int i =
1; i <= up ; i++
)printf
("%d\n"
, ans)
;return0;
}
小公尺OJ TCO 預選賽
其實粗糧oj比賽時間一直都很友好,就是題目太少,只有三題,而且質量都不咋地。a 講那麼多,答案就是k 2。隊友1分48秒切掉的題目 手速帝啊。太水就不貼 了。b 這道題題面錯漏百出,以下面為準 給定xoy平面上的n個整點,每對點 x1,y1 x2,y2 可以確定乙個矩形 矩形左上角點為 min x1...
2018 9青島網路預選賽 C
傳送門 problem c 題意 定義五個指令,判斷能否從輸入的n條指令中成功跳出迴圈,如果不能,輸出 no 反之,輸出 yes 題解 判斷某個數 0,255 是否重複來到某一指令,如果有,則肯定是個無限迴圈,輸出 no 反之,可以跳出迴圈,輸出 yes ac 1 include2 include3...
2019西湖論劍預選賽部分WP
點進鏈結發現提示 include get file 估計是檔案包含漏洞 嘗試包含index.php,發現一串base64編碼,解碼得到 a get file if a echo include get file if strpos flag a false include a 繼續解碼hint,得到...