題解 CTS2019 珍珠

2022-02-24 21:53:19 字數 2694 閱讀 4181

cts2019 珍珠

有 \(n\) 個在 \([1,d]\) 內的整數,求使可以拿出 \(2m\) 個整數湊成 \(m\) 個相等的整數對的方案數。

資料範圍:\(0\le m\le 10^9\),\(1\le n\le 10^9\),\(1\le d\le 10^5\)。

非常巧妙的題,主要要用到二項式反演、指數級生成函式和ntt

做個廣告,這是我讀過最好的生成函式講解:link

設 \(c_i\) 表示 \(i\) 這個數的出現次數。

設 \(odd=\sum [c_i\in ]\),即 \(c_i\) 奇數個數。

很明顯最多能湊成 \(\frac\) 對,按題意:

\[\begin

\frac&\ge m\\

odd&\le n-2m

\end

\]這裡有兩個特判,如果 \(n-2m<0\) 答案是 \(0\),如果 \(n-2m\ge d\) 答案是 \(d^n\)。

設 \(g(i)\) 表示 \(odd=i\) 的方案數。

設 \(f(i)\) 表示欽定 \(i\) 個 \(c_i\) 是奇數,剩下隨意的方案數(不是 \(odd\ge i\) 的方案數,這裡對一些排列會重複統計,但是反演完就沒事了)。

\[f(i)=\sum_^dg(x)\longleftrightarrow g(i)=\sum_^d(-1)^ f(x)

\]所以可以先求 \(f(i)\),用到了指數級生成函式,中間把每個 \(e\) 的冪次項展開,最後歸成卷積形式:

\[\begin

f(i)=& \left(\frac}\right)^i e^ n![n]\\

=& (e^x-e^)^i e^ \frac[n]\\

=& e^ \sum_^i(-1)^ e^ \frac[n]\\

=& e^ \sum_^i(-1)^ e^ \frac[n]\\

=& \frac\sum_^i(-1)^ e^ [n]\\

=& \frac\sum_^i(-1)^ \frac\\

=&\frac\sum_^i(-1)^ \frac (d-2j)^n\\

=&\frac\sum_^i\frac(d-2j)^n}\cdot \frac \\

\end

\]最後乙個難點是如何求:

\[g(i)=\sum_^d(-1)^ f(x)

\]感覺可以湊成卷積形式,但總差一點。嘗試把 \(f\) 和 \(g\) 都反過來,即令 \(f'(x)=f(d-x)\),\(g'(x)=g(d-x)\):

\[\begin

g(i)=&\sum_^d(-1)^ f(x)\\

=&\sum_^d(-1)^ f'(d-x)\\

=&\sum_^(-1)^ f'(x)\\

\end\\

g'(d-i)=\sum_^(-1)^ f'(x)\\

\begin

g'(i)=&\sum_^(-1)^ f'(x)\\

=&\sum_^(-1)^\frac f'(x)\\

=&\frac\sum_^ (-1)^\frac\cdot f'(x)(d-x)!\\

\end\\

\]然後就可以求 \(g(i)\) 了。

答案便是 \(\sum_^ g(i)\)。

#include using namespace std;

//start

typedef long long ll;

typedef double db;

#define mp(a,b) make_pair((a),(b))

#define x first

#define y second

#define bg begin()

#define ed end()

#define sz(a) int((a).size())

#define pb(a) push_back(a)

#define r(i,a,b) for(int i=(a),i##e=(b);ii##e;i--)

const int iinf=0x3f3f3f3f;

const ll linf=0x3f3f3f3f3f3f3f3f;

//data

const int n=1e5;

int n,m,d,ans;

//math

const int mod=998244353;

int pow(int a,int x)

const int mn=n+1;

int fac[mn],ifac[mn];

void math_init()

//poly

const int pn=mn<<2;

int f[pn],g[pn];

const int g=3,ig=pow(3,mod-2);

int rev[pn],pn;

void poly_init()

void ntt(int* a,int t){

r(i,0,pn)if(i>d>>n>>m;

if(n-2*m<0) return cout<<0<<'\n',0;

if(d<=n-2*m) return cout<祝大家學習愉快!

CTS2019 珍珠 生成函式

先考慮 m 會帶來什麼限制。sum d geq m sum d geq m sum d cnt i sum d geq 2m sum d cnt i 1 leq n 2m 也就是出現次數為奇數的數不超過 n 2m 個。這樣就意味著出現次數為偶數的數不小於 k 個。那就設 f i 表示大力硬點 i 個...

題解 CTS2019珍珠 二項式反演 卷積

題目就是要滿足這樣乙個條件 c i 代表出現次數 sum 2 ge 2m 顯然 sum c i n 所以,而且假如 c i 是 2 的約數就有正常的貢獻,如果不是就有少一點的貢獻,那麼 sum d n 2m 設 f i 為欽定有 i 種顏色出現偶數次的方案。問題瞬間就變成了haoi染色.則有 f i...

CTS2019 珍珠 二項式反演

cts2019 珍珠 考慮實際上,統計多少種染色方案,使得出現次數為奇數的顏色數 n 2 m 其實看起來很像生成函式了 n很大?感覺生成函式會比較整齊,考慮生成函式能否把n放到數值的位置,而不是維度 有標號,egf,發現奇偶性有關,其實就是e x e x 這種。確實很整齊 所以可以帶著e x化簡 如...