2021牛客暑期多校1補題記錄

2022-09-14 19:03:07 字數 4519 閱讀 2056

場上過abdfh,然後就全員摸魚去了,,

兩堆石頭,分別有\(n\)和\(m\)個。每次可以從其中一堆拿\(k(k>0)\)個,從另外一堆拿\(s\times k(s\ge 0)\)個,不能操作者輸。二者均採取最優策略,每次詢問給出\(n,m\),輸出誰贏。

\(t(t\le1e4)\)組資料,\(1\le n,m\le5e3\).

前置知識:有向圖遊戲,\(sg\)函式

解:​\((0,0)\)是必敗態。 能走到它的全是必勝態

列舉\(i,j\),若\((i,j)\)能走到的所有狀態中有乙個必敗態,那麼\((i,j)\)為必勝態,否則\((i,j)\)為必敗態。那麼我們可以用所有的必敗態來轉移。

不難發現乙個性質:對於某乙個\(i\),只存在唯一的乙個\(j\)使其成為必敗態。

證:若\((i,j_1)\)與\((i,j_2)\)均為必敗態,從其中乙個狀態可以一步走到另外乙個狀態,與必敗態的定義矛盾。

同理對於某乙個\(j\),也只存在唯一乙個\(i\)使其成為必敗態。

那麼必敗態只有5000個,暴力算一下,後面那倆個迴圈是n*調和級數的複雜度,複雜度為\(o(n^2+n^2\ln n)\)

#includeusing namespace std;

const int maxn = 5007;

bool book[maxn][maxn];

int t, n, m;

int main()

}for (int k = 1; j + k <= 5000; j++) }}

}}

cin >> t;

while (t--)

return 0;

}

簽到題 略

簽到題 略

簽到題 要用到鴿巢原理 這樣只需要暴力求小於1k的答案即可。

給定兩個長為n的陣列,執行恰好k次操作,每次操作交換a中兩個不同位置的元素,最小化

\[\sum_^|a_i-b_i|

\]sol:網上看的題解

看不懂官方題解說的什麼玩意 這個講的好啊!絕對值是數軸上兩點間的距離,題目就變成了對若干個線段的端點進行交換,使得長度總和最大。

交換不相交的線段的端點可以使得答案變優,無論a是左端點還是右端點,每次這樣的交換對答案的貢獻為\(2\times(min(a_2,b_2)-max(a_1,b_1))\),並且還能發現,交換相交線段的aa或是ab或是bb對答案的貢獻都是一樣的,所以可以直接欽定左端點為a。

貪心地取前\(k\)大的貢獻即可。

把線段的左端點和右端點分別排序,讓前\(k\)小的左端點和前\(k\)大的右端點組成線段,\(o(n\log n)\)搞一下取前\(k\)大的貢獻。相交的線段不足\(k\)對的話,一定能找到一組\(i,j\),使得交換之後他們對答案的貢獻不變,對著他們浪費掉剩下的次數就行。

#includeusing namespace std;

const int maxn = 5e5 + 7;

#define ll long long

int a[maxn], b[maxn], n, k;

ll ans;

int rd()

while (c >= '0' && c <= '9')

return s * f;

}int main()

cout << ans << endl;

return 0;

}

給乙個\(n\)個元素的集合,集合中的元素值滿足\(0\le x \le500000\),求出乙個最小的模數,使得集合中每個元素模這個數之後沒有重複。

看了眼牛客題交 全是暴力過的,跑得比正解還快

場上jyz想的是卷積的意義 直接秒了這題 但是除錯花了不少時間

考慮會衝突的情況,僅當

\[a_i-a_j\equiv 0 \mod seed

\]時會衝突。

那麼最小的模數取\(mex\\)即可

用fft/ntt求出任意兩個數之間的差值,搞兩個次數界為\(maxv\)的多項式,對於每個\(a[i]\),讓其中乙個多項式第\(a[i]\)項為1,另外乙個多項式的第\(maxv-a[i]\)項係數為1,這樣所有\(maxv+a[i]-a[j]\)項的次方項對應的係數就都是1.

之後模數從\(n\)開始列舉到\(maxv\),判斷模數及其倍數是否是\((a[i]-a[j])\),找第乙個合法的就行

#includeusing namespace std;

#define ll long long

const double pi = acos(-1.0);

const int maxn = 10 + (1 << 20), maxv = 500007;

int bit, lim;

struct complex

complex(double _x, double _y)

}a[maxn], b[maxn];

complex operator + (complex a, complex b) ;

}complex operator - (complex a, complex b) ;

}complex operator * (complex a, complex b) ;

}complex conj(complex a) ;

}void fft(complex *a, int n, int f)

for (int i = 2; i <= n; i <<= 1) ;

for (int k = 0; k < n; k += i) ;

for (int j = 0; j < m; j++)

} }if (f == -1) }}

bool vis[maxn];

int rd()

while (c >= '0' && c <= '9')

return s * f;

}int main()

lim = 1, bit = 0;

while (lim < 1000001) lim <<= 1, bit++;

//cout << lim << endl;

fft(a, lim, 1); fft(b, lim, 1);

for (int i = 0; i <= lim; i++)

fft(a, lim, -1);

for (int i = 0; i <= lim; i++)

} for (int i = n; i <= maxv; i++)

} if (flag)

} return 0;

}

a和b在長為n的排列上輪流進行操作,a先手,每一回合中,玩家選取的元素值需要比先前二人選出的所有元素值都大,除此之外,如果某人之前選擇了下標為\(i\)的元素,那麼這回合選出的元素要滿足下標比\(i\)大,如果有多個元素可供選擇,他將會等概率隨機選取。不能操作時遊戲結束,求期望回合數。

設\(f[i][j]\)表示a上一輪選了\(a[i]\),b上一輪選擇了\(a[j]\),距離遊戲結束還需要進行的回合數的期望.

那麼\[f[i][j]=\left\

1+inv[cntj[j]]\times\sum_f[k][j] & &f[i][k] & &\\

\end

\right.

\]其中\(cntj[j],cnti[i]\)分別表示「下標比當前的\(i\)大且元素值比當前的\(a[j]\)大的數的個數」,「下標比當前的\(j\)大且元素值比當前的\(a[i]\)大的數的個數」,通過倒著列舉i,j來保證下標符合要求

這個東西和後面和式裡的東西都可以字尾和搞掉,這樣就能\(o(1)\)轉移了,複雜度\(o(n^2)\)

for (int i = n; i >= 0; i--)  else if (a[j] < a[i]) 

}}

最終的答案是所有\(f[i][0]*inv[n]\)的和

#includeusing namespace std;

#define ll long long

const int maxn = 5007;

const int md = 998244353;

ll a[maxn], inv[maxn], cnti[maxn], cntj[maxn], sumi[maxn], sumj[maxn], ans, f[maxn][maxn];

int rd()

while (c >= '0' && c <= '9')

return s * f;

}int n;

int main()

for (int i = 1; i <= n; i++) a[i] = rd();

for (int i = n; i >= 0; i--) else if (a[j] < a[i]) }}

for (int i = 1; i <= n; i++) ans = (ans + f[i][0]) % md;

cout << (ans * inv[n]) % md << endl;

return 0;

}

2019牛客暑期多校 第四場 寫題記錄

給了些關鍵點 在一棵樹上 選取乙個點讓他們相聚 時間最短 其實就是求樹直徑 不過這次dfs完 我們找最遠點的時候只看標記點 第二次dfs完也一樣 include using namespace std const int maxn 1e5 5 int n,m,cnt int head maxn d ...

2020牛客多校暑期訓練營(賽後總結和補題)

ac include using namespace std intmain if c a return0 總結 這個題是第三場的第三道簽到題,需要o 1 實現題目中對字串的移動。我們隊開始是直接暴力模擬,需要o n 來實現每次移動,超時了。賽後補題,學到了用乙個指標來分割,非常地巧妙,但是其實還是...

牛客多校第九場補題(待完善)

i the crime solving plan of groundhog 題目大意 給定一組由 0 9 組成的數,組成兩個數使乘積最小。解題思路 用陣列儲存 0 9 的個數,先從 1 9 選最小的作為其中乙個乘數,其餘的數組成所能表達的最小的數。難點應該是大數乘法 這個也不難 include in...