#163: ㄊㄧˊㄐㄧㄝˇ


211096@stu.cchs.chc.edu.tw (唐狗針)

學校 : 彰化縣精誠中學
編號 : 872
來源 : [163.23.124.189]
最後登入時間 :
2025-03-27 10:04:09
a138. 子集合乘積(測資加強版) | From: [61.223.94.78] | 發表日期 : 2025-02-07 14:51

先備知識 : 動態規劃 , 模逆元

先從暴力方法開始考慮,遞迴枚舉所有組合,每個數字都有選或不選,時間複雜度$O(2^N)$。

顯然這時間在$N=3000$時不可能通過,但是選跟不選這好像在哪見過,不就是背包問題嗎。

定義$f(i,j)$為選擇完前$i$個數字後$\mod P$等於$j$的方法數。

不過轉移似乎有點問題了,如果選擇$x_i$要從$frac{j}{x_i}$轉移,但$\mod$過要怎麼除法?

所以需要模逆元,在不$\mod$時,$\div x$等價$\times x^{-1}$,$x^{-1}$的意義是$x\times x^{-1}=1$,那在$\mod P$的情況下也是要找到$x\times x^{-1} \equiv 1\pmod P$。

$P$是質數的時候,可以根據費馬小定理 : $x^{P-1} \equvi 1 \pmod P$,可以寫成 $ x \times x^{P-2} \equiv 1 \pmod P$,所以$\mod P$時$x^{-1}$就會是$x^{P-2} \bmod P$,用快速冪計算時間複雜度為$O(log P)$。

對於這題這樣就夠了,所以轉移式$f(i,j)=f(i-1,j)+f(i-1,j*x_i^{-1})$。

時間複雜度 : 狀態數有$N\times P$個,轉移時需要快速冪求模逆元,總複雜度O(NP log P),欸會TLE欸。

如果在程式一開始先預處理$1~P$的模逆然後存起來,轉移時就不用快速冪了,時間複雜度O(NP),快樂AC。

code : https://github.com/kzzz-jpg/CP/blob/main/cpp/cchs/a138.cpp

 
#164: Re:ㄊㄧˊㄐㄧㄝˇ


211096@stu.cchs.chc.edu.tw (唐狗針)

學校 : 彰化縣精誠中學
編號 : 872
來源 : [163.23.124.189]
最後登入時間 :
2025-03-27 10:04:09
a138. 子集合乘積(測資加強版) | From: [61.223.94.78] | 發表日期 : 2025-02-07 14:52

先備知識 : 動態規劃 , 模逆元

先從暴力方法開始考慮,遞迴枚舉所有組合,每個數字都有選或不選,時間複雜度$O(2^N)$。

顯然這時間在$N=3000$時不可能通過,但是選跟不選這好像在哪見過,不就是背包問題嗎。

定義$f(i,j)$為選擇完前$i$個數字後$\mod P$等於$j$的方法數。

不過轉移似乎有點問題了,如果選擇$x_i$要從$frac{j}{x_i}$轉移,但$\mod$過要怎麼除法?

所以需要模逆元,在不$\mod$時,$\div x$等價$\times x^{-1}$,$x^{-1}$的意義是$x\times x^{-1}=1$,那在$\mod P$的情況下也是要找到$x\times x^{-1} \equiv 1\pmod P$。

$P$是質數的時候,可以根據費馬小定理 : $x^{P-1} \equvi 1 \pmod P$,可以寫成 $ x \times x^{P-2} \equiv 1 \pmod P$,所以$\mod P$時$x^{-1}$就會是$x^{P-2} \bmod P$,用快速冪計算時間複雜度為$O(log P)$。

對於這題這樣就夠了,所以轉移式$f(i,j)=f(i-1,j)+f(i-1,j*x_i^{-1})$。

時間複雜度 : 狀態數有$N\times P$個,轉移時需要快速冪求模逆元,總複雜度O(NP log P),欸會TLE欸。

如果在程式一開始先預處理$1~P$的模逆然後存起來,轉移時就不用快速冪了,時間複雜度O(NP),快樂AC。

code : https://github.com/kzzz-jpg/CP/blob/main/cpp/cchs/a138.cpp


ㄚ latex爛了

 
#168: Re:ㄊㄧˊㄐㄧㄝˇ


pusapphire@gmail.com (pusapphire)

學校 : 不指定學校
編號 : 612
來源 : [111.246.60.68]
最後登入時間 :
2025-01-12 20:43:05
a138. 子集合乘積(測資加強版) | From: [111.246.63.231] | 發表日期 : 2025-02-10 01:33

先備知識 : 動態規劃 , 模逆元

先從暴力方法開始考慮,遞迴枚舉所有組合,每個數字都有選或不選,時間複雜度$O(2^N)$。

顯然這時間在$N=3000$時不可能通過,但是選跟不選這好像在哪見過,不就是背包問題嗎。

定義$f(i,j)$為選擇完前$i$個數字後$\mod P$等於$j$的方法數。

不過轉移似乎有點問題了,如果選擇$x_i$要從$frac{j}{x_i}$轉移,但$\mod{}$過要怎麼除法?

所以需要模逆元,在不$\mod{}$時,$\div x$等價$\times x^{-1}$,$x^{-1}$的意義是$x\times x^{-1}=1$,那在$\mod P$的情況下也是要找到$x\times x^{-1} \equiv 1\pmod P$。

$P$是質數的時候,可以根據費馬小定理 : $x^{P-1} \equiv 1 \pmod P$,可以寫成 $ x \times x^{P-2} \equiv 1 \pmod P$,所以$\mod P$時$x^{-1}$就會是$x^{P-2} \bmod P$,用快速冪計算時間複雜度為$O(log P)$。

對於這題這樣就夠了,所以轉移式$f(i,j)=f(i-1,j)+f(i-1,j*x_i^{-1})$。

時間複雜度 : 狀態數有$N\times P$個,轉移時需要快速冪求模逆元,總複雜度O(NP log P),欸會TLE欸。

如果在程式一開始先預處理$1~P$的模逆然後存起來,轉移時就不用快速冪了,時間複雜度O(NP),快樂AC。

code : https://github.com/kzzz-jpg/CP/blob/main/cpp/cchs/a138.cpp

與其在$f(i,\ ...)$的時候找$f(i-1,\ ...)$,不如改成在$f(i,\ ...)$的時候更新$f(i+1,\ ...)$,就不用模逆元了

dp[0][ array[0] ] = 1
for i in 0..n-1:
    dp[ i+1 ] = copy(dp[i])
    for j in 0..P:
        dp[ i+1 ][ j * array[i] % P ] += dp[i][j]
answer: dp[n][1] % P

 
#169: Re:ㄊㄧˊㄐㄧㄝˇ


pusapphire@gmail.com (pusapphire)

學校 : 不指定學校
編號 : 612
來源 : [111.246.60.68]
最後登入時間 :
2025-01-12 20:43:05
a138. 子集合乘積(測資加強版) | From: [111.246.63.231] | 發表日期 : 2025-02-10 01:33

先備知識 : 動態規劃 , 模逆元

先從暴力方法開始考慮,遞迴枚舉所有組合,每個數字都有選或不選,時間複雜度$O(2^N)$。

顯然這時間在$N=3000$時不可能通過,但是選跟不選這好像在哪見過,不就是背包問題嗎。

定義$f(i,j)$為選擇完前$i$個數字後$\mod P$等於$j$的方法數。

不過轉移似乎有點問題了,如果選擇$x_i$要從$frac{j}{x_i}$轉移,但$\mod{}$過要怎麼除法?

所以需要模逆元,在不$\mod{}$時,$\div x$等價$\times x^{-1}$,$x^{-1}$的意義是$x\times x^{-1}=1$,那在$\mod P$的情況下也是要找到$x\times x^{-1} \equiv 1\pmod P$。

$P$是質數的時候,可以根據費馬小定理 : $x^{P-1} \equiv 1 \pmod P$,可以寫成 $ x \times x^{P-2} \equiv 1 \pmod P$,所以$\mod P$時$x^{-1}$就會是$x^{P-2} \bmod P$,用快速冪計算時間複雜度為$O(log P)$。

對於這題這樣就夠了,所以轉移式$f(i,j)=f(i-1,j)+f(i-1,j*x_i^{-1})$。

時間複雜度 : 狀態數有$N\times P$個,轉移時需要快速冪求模逆元,總複雜度O(NP log P),欸會TLE欸。

如果在程式一開始先預處理$1~P$的模逆然後存起來,轉移時就不用快速冪了,時間複雜度O(NP),快樂AC。

code : https://github.com/kzzz-jpg/CP/blob/main/cpp/cchs/a138.cpp

與其在$f(i,\ ...)$的時候找$f(i-1,\ ...)$,不如改成在$f(i,\ ...)$的時候更新$f(i+1,\ ...)$,就不用模逆元了

dp[0][ array[0] ] = 1
for i in 0..n-1:
    dp[ i+1 ] = copy(dp[i])
    for j in 0..P:
        dp[ i+1 ][ j * array[i] % P ] += dp[i][j]
answer: dp[n][1] % P

打錯 是 dp[ i+1 ][ j * array[i+1] % P ] += dp[i][j]

 
ZeroJudge Forum