題目描述如下:甲乙丙丁四人遊戲,甲有二整數 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 看到這個題目描述只有一行我心頭就湧上一股不祥的預感 一般這種題 都比較 那啥 是的,這個題我又寫炸了 好的讓我們來...