HIT2018春校賽 I題 略解

2021-10-02 08:01:49 字數 3126 閱讀 1519

題目描述如下:甲乙丙丁四人遊戲,甲有二整數 x 和 y,四人已知 2 <= x <= y <= n,但乙丙丁未知 x 和 y 確值。現在,甲告訴乙 x + y 的值,甲告訴丙 x * y 的值,下面四人對話:

乙:我不知道 x 和 y 的確值,但我知道丙不知道 x 和 y 的確值;

丙:我原不知道 x 和 y 的確值,但我現在知道 x 和 y 的確值了;

乙:我現在也知道 x 和 y 的確值了;

丁:我現在也知道 x 和 y 的確值了。

要求給定 n,判斷這些話是否能被同時滿足,輸出 yes 或 no。t 組資料,1 <= t <= 200,2 <= n <= 3000。

據說此題為 hit2018春校賽i題,真實性不論,本題還是比較有意思的。可以注意到,四人中只有丁和解題者是處於同一資訊狀態下的。換句話說,若丁最後確實知道了 x 和 y 的確值,那麼我們也可以知道 x 和 y 的確值。設初始解集 p

=p = \, y \in \mathbb\}

p=,下面就根據對話逐步縮小解集 p,直至僅剩餘乙個元素,即為解。若剩餘多個元素或解集為空,即條件不能被同時滿足。

對於第一句前半乙的話和第二句前半丙的話,我們可以初步縮小解集。將解集 p 中數對 (x, y) 按 x * y 的值劃為不超過 n∗n

n * n

n∗n 個數簇,x * y 的值相同的劃為同一數簇,不同的劃為不同數簇。若某一數簇內只有乙個數對,則該數對必不為解,從解集中除去。這樣處理後的解集 p 中所有數對可以使得第二句前半丙的話為真。對於第一句前半乙的話則可以簡化處理,6 <= x + y <= n + n - 2 即可。

接下來處理第一句後半乙的話,對於任一 s∈[

6,n+

n−2]

s \in [6, n + n - 2]

s∈[6,n

+n−2

],將解集 p 中所有 x + y = s 的數對 (x, y) 取出,構成子集 q

sq_s

qs​。換句話說,取集合 qs∈

pq_s \in p

qs​∈

p 使得 ∀(x

,y)∈

qs,x

+y=s

\forall (x, y) \in q_s, x + y = s

∀(x,y)

∈qs​

,x+y

=s並且 ∀(x

,y)∈

p−qs

,x+y

≠s

\forall (x, y) \in p - q_s, x + y ≠ s

∀(x,y)

∈p−q

s​,x

+y​

=s。對於任一 q

sq_s

qs​,若 ∃(x

,y)∈

qs

\exist (x, y) \in q_s

∃(x,y)

∈qs​

使得 (x, y) 所在數簇僅有乙個數對,則集合 q

sq_s

qs​ 內所有數對必不為解,從解集中除去。這樣處理後的解集 p 中所有數對可以使得第一句後半乙的話為真。

對於第二句後半丙的話,根據當前解集 p 重新構建數簇,若某一數簇內有超過乙個數對,則該數簇內所有數對必不為解,從解集中除去。對於第三句乙的話,根據當前解集 p 重新構建 q

sq_s

qs​,若某一 q

sq_s

qs​ 內有超過乙個數對,則該 q

sq_s

qs​ 內所有數對必不為解,從解集中除去。

最後,若解集 p 中僅剩餘乙個元素,則丁和我們均知道了 x 和 y 的確值,否則這些話不能被同時滿足。這樣,我們得到了乙個樸素的演算法。

**如下:

#include

#define max_n2 (9000005)

#define max_n22 (5000000)

struct pr

p[max_n22]

;int cnt[max_n2]

;bool

fgr(

int n)

if(m==0)

return

false

;for

(int i=

4;i<=n*n;i++

) cnt[i]=0

;for

(int i=

0;i) cnt[p[i]

.x*p[i]

.y]++

;for

(int i=

0;i(cnt[p[i]

.x*p[i]

.y]>1)

p[i]

.x=p[

--m]

.x,p[i--

].y=p[m]

.y;if

(m==0)

return

false

;for

(int i=

4;i<=n+n;i++

) cnt[i]=0

;for

(int i=

0;i) cnt[p[i]

.x+p[i]

.y]++

;for

(int i=

0;i(cnt[p[i]

.x+p[i]

.y]>1)

p[i]

.x=p[

--m]

.x,p[i--

].y=p[m]

.y;return m==1;

}int

main()

很明顯,上面的**並不能在時間限制內跑完,需要優化。最容易想到的是打表,實施後發現跑完 2 到 3000 所有資料花費時間不超過一分鐘。不過這使得**略長,於是考慮乙個問題:使得所有話成立的 n 是否構成了乙個整數連續的區間?當 n 很小的時候,作為解的數對不在初始解集裡;當 n 充分大的時候,原本成立的解變得不成立或不唯一了。但是,也可能隨 n 增大而產生新解。也就是說,從理論上不能證明使得解成立的 n 取值為乙個整數區間。但事實上,觀察打出的表可以得出,使得數對成立的 n 構成了乙個區間,該區間為 [62, 865],當 n 取值為該區間內整數時,存在唯一數對解 (4, 13)。

優化**如下:

#include

intmain()

xdoj 2018校賽 網路賽

第一次參加校賽,相比於之前的網路賽,感覺這次難度還行,不算難也不算簡單。先簡單說說前面幾道題吧 a 水題,找規律 b 水題,最小公倍數 c 稍稍有點難度,先排序,仔細考慮即可 d 水題,找規律 e bfs打表 f 矩陣快速冪遞推 g 找到一一對應的方法bfs 好了,仔細說說最後三題吧。h 一道看上去...

春校賽 求索溪邊的磚

春校賽 求索溪邊的磚 10分 眾所周知,求索溪邊堆了很多磚。這些磚的長寬高規格不太一樣。一共有n種磚,第i種磚的長寬高分別為,每種磚有無限多。學校開展桃花節需要將這些磚搬走,高階搬磚工小胖接了活。我們搬磚時都是將磚疊成一摞再搬。小胖的力氣非常大,當然希望盡可能的摞到最高,但是只有上面磚的底面兩條邊都...

NOIP2018校模擬賽 T1 階乘

有n個正整數a i 設它們乘積為p,你可以給p乘上乙個正整數q,使p q剛好為正整數m的階乘,求m的最小值。共兩行。第一行乙個正整數n。第二行n個正整數a i 共一行乙個正整數m。16 看到這個題目描述只有一行我心頭就湧上一股不祥的預感 一般這種題 都比較 那啥 是的,這個題我又寫炸了 好的讓我們來...