10 14 牛客提高集訓營5

2022-04-02 15:13:08 字數 3501 閱讀 3014

目錄比賽鏈結

題目鏈結

首先容斥一下,\(ans=(r_1,r_2)-(r_1,l_2-1)-(l_1-1,r_2)+(l_1-1,l_2-1)\)。\((x,y)\)表示\(l_1=l_2=0,\ r_1=x,\ r_2=y\)時的答案。

因為是異或,我們按位考慮。

對於\((r_1,r_2)\),考慮這種特殊情況:\(r_1=2^n-1,\ r_2=2^m-1\)(假設\(n\leq m\))。

從\([0,2^n)\)中任取乙個\(x\),\([0,2^m)\)中任取乙個\(y\),那麼\(x^y\)還在\([0,2^n)\)內。

對於任意乙個\(z\in[0,2^n)\),它的前\(n-m\)位是由\(x\)確定的,後\(m\)位由\(x,y\)共同確定。那麼對於\(x\)的後\(m\)位的\(2^m\)種取值,\(y\)都有唯一的值使得\(x^y=z\)。所以我們算一下\([0,2^n)\)中有多少個\(p\)的倍數,再乘上\(2^m\)就行了。

考慮更一般的情況。如果列舉\(r\)的某一位\(1\)選\(0\),那麼後面所有位可以隨意確定。比如\(r=(1011)_2\),可以將它拆成\(0???,100?,1010\)三個區間(區間左端點為\(0\)),這樣就對應三個形如\(a\times2^n+[0,2^n)\)的區間(\(a\)就是列舉的\(1\)之前的字首)。當然\(1011\)本身不會計算到,讓\(r+1\)就行了。

這樣我們就把任意區間拆成了\(o(\log n)\)個字首固定,後面隨便放的區間。

考慮對於\(r_1,r_2\),設拆出的區間分別是\(a_1\times2^n+[0,2^n)\)和\(a_2\times2^m+[0,2^m)\),且\(n\geq m\)。那麼從這兩個區間中任取兩個數異或,結果的後\(n\)位可以任意定,剩餘高位由\(a_1\times2^n\ ^\ a_2\times2^m\)確定。異或的結果是乙個區間,區間中任意數同樣有\(2^m\)種選擇得到。算一下區間中有多少個數整除\(p\)就行了。(因為有個\([0,2^n)\)的數,所以區間下界的後\(n\)位為全\(0\),上界就全\(1\),其餘高位由\(a_1\times2^n\ ^\ a_2\times2^m\)決定)。

#include #include #include #define gc() getchar()

#define bit 59

#define mod 998244353

typedef long long ll;

inline ll read()

//ll calc(ll a,ll b,ll m)//兩種寫法

//^m 2^i*a_i\)。

怎麼判斷當前\(a_i\)的選擇方案是否合法呢?也就是判是否存在尤拉迴路。那麼令\(dgr_i\)為\(i\)點度數,那麼若滿足\(\forall i,dgr_i\%2=0\),方案合法。

好了以上是廢話。我們先求最小生成樹。

因為樹邊權值都小於非樹邊,且\(2^k>\sum_^2^i\),所以如果要走一條權值大的非樹邊兩次,完全可以多繞一圈樹邊代替,且同樣只影響路徑端點的兩個點的度數奇偶性。

我們還可以發現,\(1\leq a_i\leq2\)。對生成樹dfs一遍,根據點的度數確定一下\(x\)需要走到\(fa[x]\)的邊多少次就行了。

\(1\)節點沒有到父節點的邊,但因為所有點度數和為偶數,所有它的度數也一定是偶數。

//107ms 16476kb

#include #include #include //#define gc() getchar()

#define maxin 300000

#define gc() (ss==tt&&(tt=(ss=in)+fread(in,1,maxin,stdin),ss==tt)?eof:*ss++)

#define mod 998244353

typedef long long ll;

const int n=5e5+5;

int pw[n],enum,h[n],to[n<<1],nxt[n<<1],len[n<<1],fa[n],dgr[n];

ll ans;

char in[maxin],*ss=in,*tt=in;

inline int read()

inline void ae(int u,int v,int w)

int find(int x)

void dfs(int x,int fa)

}int main()

dfs(1,1);

printf("%lld\n",ans%mod);

return 0;

}

題目鏈結

首先串\(t\)有\(\binom\)種可能。

先生成串\(s\)再判斷\(t\)是\(s\)的子串行很麻煩。我們可以往\(t\)中加入\(a-c\)個\(0\)和\(b-d\)個\(1\)來得到\(s\)。那麼所求即為有多少種加入\(0/1\)的方案由\(t\)得到\(s\)。

顯然多餘的\(0/1\)是哪都可以加的。但是直接這麼算會算重。比如000加乙個0,有\(4\)個位置可選,但實際方案數只有1種。

考慮比如0001要加入乙個0,只要欽定0只能放在那個1前面,就不會算重了。再比如00011001,每個1前(且只在\(1\)前)可以放若干個0,方案都是不同的。

所以實際上\(0\)可以放的位置只有\(d\)個(即\(1\)的個數)(當然乙個位置可以放多個\(0\))。

另外\(t\)的末尾是可以任意放\(0/1\)的。那我們列舉\(t\)的末尾放多少個\(0/1\),方案數可以用組合數算。同樣其餘的\(0/1\)只能放在前面確定的一些位置,方案數同樣可以用組合數\(o(1)\)計算(就是\(n\)個球放入\(m\)個盒子,允許盒子為空,即將\(n\)個球分成\(m\)組)。

設在前面放\(x\)個\(0\),\(y\)個\(1\),則方案數為:$$\binom\times\binom\times\binom$$

因為有\(c-1,d-1\),所以要特判\(c,d\)為\(0\)的情況。而且這樣算只與\(0/1\)數量有關,最後可以直接乘\(\binom\)。

#include #include #include #include #define gc() getchar()

#define mod 1000000007

typedef long long ll;

const int n=4005;

int fac[n],ifac[n];

inline int read()

inline int fp(int x,int k)

#define c(n,m) (1ll*fac[n]*ifac[m]%mod*ifac[(n)-(m)]%mod)

int main()

9 16 牛客提高集訓營2

目錄考試 期望得分 100 40 10 實際得分 100 10 10 非要用滾動陣列,還不好好清空,丟了30分吧。比賽鏈結 題目鏈結 拆一下方差的式子就可以 o 1 得到要求的值了。出題人 資料是精心設計的,剛好不會爆longlong。是的,這是在你原題面乘 n 1 而不是乘 n 1 2 的情況下。...

牛客CSP S提高組賽前集訓營5(待更)

題目描述 神樹大人造了乙個長為n的01序列,並邀請無所事事的神j來和他博弈。每一輪裡,若這個序列的第1項是0,那麼神樹大人可以選擇讓它不變或者變成1 若這個序列的第1項是1,那麼神j可以選擇讓它不變或者變成0。接著對這個序列進行旋轉操作 即將第1項放到第n項的後面,其他項依次替補。如果這個序列變為全...

牛客CSP S提高組賽前集訓營5 解題報告

linker 總分 100 100 40 240 結論題。無論如何神j都會贏。最優決策 神樹變化了我就不變,神樹不變我就變化。includeusing namespace std typedef long long ll const int mod 998244353 inline ll pow l...