數學專題總結

NOIP內容.

Catalan數

基礎

\((0,0)\) 走到 \((n,n)\) 不經過對角線的方案數.
答案爲:\(\frac{C(n,m)}{(n+1)}\)
證明:
我們新增一個點 \((n-1,n+1)\) 即終點左上角的點,我們需要證明:所有從經過對角線到終點的路徑和從 \((0,0)\)\((n-1,n+1)\)的路徑一一對應,我們用總方案-不合法路徑,就可以得到答案了

首先我們明確穿過對角線的路徑一個經過線L2,L2爲 \((0,1)\)\((n-1,n)\) 這一條直線。顯然,從 \((0,0)\)\((n-1,n+1)\) 的路徑一定經過L2,我們設與L2的交點爲M,將M到終點的路徑沿着L2對摺,就對應一條到終點的路徑,並且一定經過對角線,所以到 \((n-1,n+1)\) 的路徑>=到\((n,n)\)的路徑.

然後對於到 \((n,n)\) 的所有路徑沿着L2翻折之後,也對應一條到 \((n-1,n+1)\)的路徑,所以到 \((n-1,n+1)\) 的路徑<=到\((n,n)\)的路徑

綜上:到 \((n-1,n+1)\) 的路徑=到\((n,n)\)的路徑
所以答案爲:\(C(2n,n)-C(2n,n-1)=\frac{C(n,m)}{(n+1)}\)

應用(摘自NaVi-Awson)

1.括號序列計數

再來看一個問題:有多少種不同的長度爲 的括號序列?
首先一個括號序列是指 (), ()(), (())() 這樣的由括號組成的序列,並且沒有左右括號無法匹配的情況
我們可以將長度爲 \(2n\) 的括號序列映射成剛剛所說的路徑:首先對於左括號,那麼就向右走一個單位長度,對於右括號,那麼就向上走一個單位長度,由於括號序列合法,那麼每次向右走的次數不會少於向上的次數,也就是這條路徑不會在 \(y=x\) 之上。再考慮每一條這樣的路徑,也能夠對應到一種合法的括號序列,因此,長度爲 \(2n\) 的括號序列的方案數就是 \(Cn\)

2.出棧順序

現在來考慮你有 \(n\) 個元素(元素之間是沒有區別的)和一個棧,每次可以將一個元素入棧,或者將棧頂元素彈出,問有多少種可能的操作序列,這可以將問題對應成括號序列,入棧爲左括號,出棧爲右括號,因此方案數也是 \(Cn\)

3.排隊問題

現在有 \(2n\) 個人,他們身高互不相同,他們要成兩排,每一排有 \(n\) 個人,並且滿足每一排必須是從矮到高,且後一排的人要比前一排對應的人要高,問有多少種排法

我們考慮先把這些人從矮到高排成一排,那麼現在來分配哪個人在前,哪個人在後,例如有 \(6\) 個人,身高是 1, 2, 3, 4, 5, 6

那麼我們用 1 表示這個人應該在後排,0 表示這個人應該在前排,例如說 100110 表示兩排分別是 2, 3, 6 和 1, 4, 5 這是不合法的

那麼合法方案應該是怎麼樣的呢?後排要比前排對應的人高,也就是說 0 的出現次數在每一個地方都不應該小於 1,這恰恰又是一個括號序列,因此,方案仍然是 Catalan 數

4.二叉樹計數

現在你需要統計有多少種不同的 \(n\) 個結點的二叉樹
此處輸入圖片的描述
圖上的是 \(3\) 個結點的二叉樹,一共有 \(5\) 種方案
樸素的想法是由於二叉樹是遞歸定義的,可以考慮使用遞推方法
我們可以用 \(fn\) 表示有 \(n\) 個結點的二叉樹的方案數(空樹算一種,即 \(f_{0}=0\) ),那麼枚舉子樹大小可以得到方程 \(f_n=\sum_{i=0}^{n-1}f_if_{n-i-1}\)
如果直接計算,你需要 \(O(n^2)\) 的時間

現在我們換一個角度來想,對這棵二叉樹進行遍歷,並且考慮一個括號序列,當第一次遇到這個結點的時候,在括號序列末尾添加一個左括號,在從左子樹回到這個結點的時候,在括號序列中添加一個右括號,這樣,將每一種不同的二叉樹都對應到了一種不同的括號序列,同樣對於每一種不同的括號序列都可以找到對應的一種不同的二叉樹,因此,有 \(n\) 個結點的二叉樹的數量也是 \(Cn\)

遞推式

\(C_{n+1}=\sum_{i=0}^{n}C_i*C_{n-i}\)


第一類斯特林數

含義

\(n\) 個不同的人圍成 \(m\) 個不同的桌子的方案數 , 記爲 \(S(n,m)\)

遞推式

\(S(n,0)=0,S(0,0)=1\)
\(S(n,m)=S(n-1,m-1)+S(n-1,m)*(n-1)\)
分別對應把第 \(n\) 個人放到新加入的第 \(m\) 個桌子中和放到任意一個人的左邊

性質

第一類斯特林數 \(S(n,m)\)\(x\)\(n\) 次上升冪展開式中 \(x^m\) 項的係數 , 即:
排列數 \(P(n,k)\) 爲在 \(n\) 個人中選 \(k\) 個人的排列方案數
\(P(n,k)=n*(n-1)*(n-2)*...*(n-k+1)\)
\(P(n,k)=S(k,k)*n^k-S(k,k-1)*n^{k-1}+...+S(k,k-i)*n^{k−i}−…S(k,0)*n^0\)
\(P(n,k)=\sum_{i=0}^{k}(-1)^{k-i}S(k,i)*n^{i}\)
同樣可以寫成上升冪的形式 \(x^{n↑}=x*(x+1)*(x+2)...*(x+n-1)=\sum_{k=0}^{n}S(n,k)*x^k\)
可以用遞推式來歸納證明 .
這樣我們就可以通過 \(O(n*log^2)\) 的分治 \(FFT\) 合併出一個長度爲 \(n\) 的上升冪展開的多項式 , 求出第一類斯特林數的某一行的值了 .


第二類斯特林數

含義

\(n\) 個有區別的球放入 \(m\) 個無區別的盒子中的方案數 ,記爲 \(S(n,m)\) ,其中集合內是無序的 .

遞推式

\(S(n,0)=0,S(0,0)=1\)
\(S(n,m)=m*S(n-1,m)+S(n-1,m-1)\)

證明:

1.若單獨一個集合,則方案數等價於\(S(n-1,m-1)\)
2.若不是單獨一個集合,則他可以在之前任意 \(j\)個集合裏,方案爲 \(S(n-1,m)*m\)

展開式

\(\frac{1}{m!}\sum_{i=0}^{m}(-1)^i*C_{m}^{i}*(m-i)^n\)
這個式子本質是對 至少有\(i\)個盒子爲空進行容斥
拆開組合數,併合並得到:
\(\sum_{i=0}^{m}\frac{(-1)^{i}}{i!}*\frac{(m-i)^{n}}{(m-i)!}\)
這個東西可以 \(NTT\) 優化


錯排

定義

滿足 \(a[i]!=i\) 的排列的方案數,設爲 \(D(n)\)

遞推式

\(D(n)=(n-1)*(D(n-1)+D(n-2))\)
首先新加入一個元素,我們先把它放到最後
選擇原來的 \((n-1)\) 個元素的錯排中的任意一個和新加入的交換,依舊是錯排,方案爲 \((n-1)*D(n-1)\)
原來的排列不必爲錯排,若有一個元素滿足 \(a[i]=i\) 也可以和新加入的交換,方案爲 \((n-1)*D(n-2)\)

推廣

\(D(n)=n!*(1-\frac{1}{1!}+\frac{1}{2!}-\frac{1}{3!}+(-1)^n\frac{1}{n!})\)
這個可以用遞推式構造出來,這裏用容斥來簡單的證明:
總方案爲 \(n!\) ,我們要減去至少有一個不滿足的,方案爲 \(\frac{n*(n-1)!}{1!}\)
加上有至少有兩個不滿足的,方案爲 \(\frac{n*(n-1)*(n-2)!}{2!}\)
也就是說至少有 \(m\) 個不滿足的方案爲 \(C_{n}^{m}*(n-m)!\)
發現每一項分子都是 \(n!\) ,提出即可得到上式


羣論

burnside

\(L=\frac{1}{|G|}\sum_{i=1}^{|G|}c1_{i}\)
表示 等價類的個數\(L\)=每一種置換的不動點個數 除以 總置換個數\(|G|\)

證明

其中 \(c1_i\)\(1\) 表示的是長度爲 \(1\) 的循環個數
\(Z_k\) 表示使元素 \(k\) 不變化的置換集合, \(E_i\) 爲元素 \(i\) 在置換羣 \(G\) 的所有操作下能到達的所有元素
\(\sum_{i=1}^{|G|}c1_i=\sum_{i=1}^{n}|Z_i|\)
\(\sum_{i=1}^{n}|Z_i|=\sum_{i=1}^{L}|E_i||Z_i|=L|G|\)
所以 \(L=\frac{1}{|G|}*\sum_{i=1}^{|G|}c1_{i}\)
其中 \(\sum_{i=1}^{n}|Z_i|=\sum_{i=1}^{L}|E_i||Z_i|\) , 是因爲所有等價類元素的 \(|Z_i|\) 是相等的
\(|E_i||Z_i|=|G|\) 是因爲 軌道大小×穩定化子數=變換個數(證明參考<>)

\(burnside\)的主要用法就是暴力枚舉所有的置換,並計算其不動點的個數

Polya

\(L=\frac{1}{|G|}\sum_{a_i∈|G|}m^{|k_i|}\)
表示有 \(m\) 種顏色可以選,其中第 \(i\) 中置換有 \(|k_i|\) 個循環
原因可以簡單的想一下: 在一個置換中,不同循環之間的顏色選擇互不影響,且相同循環必須顏色相同
且在每一種置換中,同一個等價類都被算了一次,所以要除以 \(|G|\)

\(Polya\)的關鍵在於求出每一種置換的循環個數,從而得出等價類個數


中國剩餘定理

//x%p[i]=m[i]
ll crt(){
   ll lcm=1,r,tot=0,x,y;
   for(int i=1;i<=n;i++)lcm*=p[i];
   for(int i=1;i<=n;i++){
      r=lcm/p[i];
      exgcd(r,p[i],x,y);
      tot=(tot+r*x*m[i]%lcm)%lcm;
   }
   return (tot+lcm)%lcm;
}

一些理解

結論:

1.幾個數相加,如果存在一個加數,不能被數 \(x\) 整除,那麼它們的和,就不能被整數 \(x\) 整除
2.兩數不能整除,我們擴大被除數,那麼餘數也會擴大相同的倍數,縮小也成立
3.如果 \(a\) \(mod\) \(b=c\),那麼 \((a-k*b)\) \(mod\) \(b=c\)

推斷:

我們先求出所有 \(p[i]\) 的最小公倍數(\(lcm\)),然後我們用 \(lcm/p[i]\) 得到當前數的基數設爲 \(y\),這個基數滿足性質:與 \(p[i]\) 互質,能被 \(p[j],j\neq i\) 整除,由於滿足結論 \(2\),我們擴大 \(y\) ,直到 \(y \mod p[i]=m[i]\),這裏可以用 \(exgcd\) 求出。因爲滿足定理 \(1\) ,所以相加起來得到一組解,但是此時並不是最小的解,根據定理 \(3\),我們將解 \(mod\) \(lcm\)得到最小解.


Lucas定理

\[C(n,m)\%p=C(n\%p,m\%p)*C(n/p,m/p)\]
觀察式子,其優勢在於 \(n,m\)取值較大,而模數較小時使用,複雜度是 \(O(log)\).
對於式子的第二項我們遞歸求解.

inline ll C(int n,int m){
    return mul[n]*ni[m]%mod*ni[n-m]%mod;
}

inline ll Lucas(int n,int m){
    if(!m)return 1;
    return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
}

擴展盧卡斯

盧卡斯運用的條件是模數P爲質數.
擴展盧卡斯:對P進行質因數分解,得到許多形如 \(p^e\) 的質因子,直接用組合數公式算,然後中國剩餘定理合併.
難點在於階乘和模數不互質,不能求逆,考慮階乘取模.

1.對於 \(p\) 的倍數我們單獨提出算,分子分母相減就可以得到 \(p\) 相除後的值
2.剩下的部分與 \(p\) 互質,按 \(\%p\) 的值分塊算.
3.提出來的 \(p\) 的係數,發現形式和 \(2\) 部分相同,直接遞歸處理

舉個例子:
\(7!\) \(mod\) \(2\)
\(7!=1*2*3*4*5*6*7=1*3*5*7*2^3*(1*2*3)\)

\(1,3,5,7\) 部分分塊算,\(1,2,3\) 部分當做新的階乘 \(!(n/p)\) 遞歸處理即可

對於算 \(p\) 的倍數的部分,可以單獨算,設\(x\) 表示 \(p\)\(!n\) 中出現的次數.
顯然:\(x=\sum_{i=1}n/p^i\)

預處理階乘之後的話複雜度就是 \(O(log_{p}n)\)

inline void exgcd(ll a,ll b,ll &x,ll &y){
    if(!b)x=1,y=0;
    else exgcd(b,a%b,y,x),y-=a/b*x;
}
inline ll ni(ll a,ll b){
    ll x,y;
    exgcd(a,b,x,y);
    x%=b;
    if(x<0)x+=b;
    return x;
}
inline ll Fac(ll n,ll p,ll pr){
    if(n==0)return 1;
    ll re=0;
    for(ll i=2;i<=pr;i++) if(i%p) re=re*i%pr;
    re=qm(re,n/pr,pr);
    ll r=n%pr;
    for(ll i=2;i<=r;i++) if(i%p) re=re*i%pr;
    return re*Fac(n/p,p,pr)%pr;
}
inline ll C(ll n,ll m,ll p,ll pr){
    if(n<m)return 0;
    ll c=0;
    for(RG ll i=n;i;i/=p)c+=(i/p);
    for(RG ll i=m;i;i/=p)c-=(i/p);
    for(RG ll i=n-m;i;i/=p)c-=(i/p);
    if(c>=K)return 0;
    ll x=Fac(n,p,pr),y=Fac(m,p,pr),z=Fac(n-m,p,pr);
    ll re=x*ni(y,pr)%pr*ni(z,pr)%pr*qm(p,c,pr)%pr;
    return (mod/pr)*ni(mod/pr,pr)%mod*re%mod;
}
inline ll Lucas(ll n,ll m){
    ll x=MOD,re=0;
    for(ll i=2;i<=MOD;i++) if(x%i==0){
        ll pr=1;
        while(x%i==0) x/=i,pr*=i;
        re=(re+C(n,m,i,pr))%MOD;
    }
    return re;
}

高斯消元

性質

一、交換變換:\(Ri<->Rj\),表示將\(Ri\)\(Rj\)的所有元素對應交換
二、倍法變換:\(Ri=Ri*k\),表示將\(Ri\)行的所有元素都乘上一個常數k
三、消去變換:\(Ri=Ri+Rj*k\),表示將\(Ri\)行的所有元素對應的加上 \(Rj\) 行元素的\(k\)
這些變換不會影響最後的解

思路

利用上面的交換求出一個倒三角,再反推回去.
\[ \begin{matrix} x1 & x2 & x3 \\ 0 & x2 & x3 \\ 0 & 0 & x3 \end{matrix} \tag{1} \]
我們一列一列消除,以此類推得到最後一行的一個未知數,然後我們就可以反推回去了.

inline void solve(){
    for(int l=1;l<=n;l++){
        int maxid=l;
        for(int i=l+1;i<=n;i++)
            if(fabs(a[i][l])>fabs(a[maxid][l]))maxid=i;
         //找到滿足這一列最大的一行
        if(maxid!=l)swap(a[maxid],a[l]);
        if(a[l][l]==0){puts("No Solution");return ;}
         //多解情況
        for(int i=l+1;i<=n;i++){
            double tmp=a[l][l]/a[i][l];
            for(int j=l;j<=n+1;j++)
                a[i][j]=a[l][j]-tmp*a[i][j];
        }
    } 
        //反推求解
    for(int i=n;i>=1;i--){
        for(int j=i+1;j<=n;j++)
            a[i][n+1]-=a[i][j]*a[j][n+1];
        a[i][n+1]/=a[i][i];
    }
    for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]);
}

特殊情況

1.無解:如果有一行方程的所有變量的係數都爲0,而常數項不爲0,方程就無解.
2.多解:如果有一行方程的所有變量的係數都爲0,常數項也爲0,那麼這就說明出現了自由元.
自由元:若這一個元素任意取值其他元素都有唯一的解與其對應,則稱爲自由元,方程解的個數一般就是 \(x^n\) , \(n\) 是自由元的個數 , \(x\) 是能取的值的數量.


線性基

這可能是假的數學,本蒟蒻也不太懂.

例題

給定n個整數(數字可能重複),求在這些數中選取任意個,使得他們的異或和最大

solution

如果給你的每一個數的最高位的1都在不同位置,那麼我們就可以從高位到低位按位貪心,線性基就是把這n個數轉化爲這個等價的形式.

性質

1.通過線性基中元素 \(xor\) 出的數的值域與原來的數 \(xor\) 出數的值域相同
2.線性基的一些子集 \(xor\) 起來的值不爲0,因爲構造時保證每一個元素都有一個最高位1.

線性基的構造

1.我們求出最高位1爲當前位置的一個數,如果當前位沒有數,我們就加入這個數
2.如果當前位有數字,我們就把當前加入的數 \(x\) \(xor\) \(a[j]\)\(a[j]\)爲當前位置上的數,然後繼續尋找1的情況,這樣保證了最高位1不再爲當前位.

for(int i=1;i<=n;i++){
    scanf("%lld",&x);
    for(int j=50;j>=0;j--){
        if(!(x>>j&1))continue;
        if(!a[j]){a[j]=x;break;}
        else x^=a[j];
    }
    long long ans=0;
    for(int i=50;i>=0;i--)
        if((ans^a[i])>ans)ans^=a[i];
    cout<<ans<<endl;
}

快速傅里葉變換

一般用來求卷積即 \(Cn=\sum_{i=1}^{n}a_{i}*b_{n-i}\)
這裏稱 \(C\)\(ab\) 的卷積
同時這也是多項式乘法的係數,可以用來加速多項式乘法

算法框架

1.轉化係數表示法爲點值表示法
2.利用點值表示法的性質 \(Ci=ai*bi\) ,可以 \(O(n)\) 的求出相乘後的點值
3.將點值表示法再次轉回係數表示法

DFT

DFT即轉化係數表示法爲點值表示法的過程,複雜度是 \(O(nlogn)\) 的.

點值表示法

對於多項式 \(A(x)=\sum_{i=1}^{n}aix^{i}\)
我們代入一個 \(x0\) 可以得到一個值 \(A(x0)\),所以一個多項式又可以用n+1個點值表示多項式,那麼就稱 \({(xi,A(xi)):0<=i<=n}\) 爲多項式的點值表示.

一個點值表示可以用秦九韶算法 \(O(n)\) 的算出,要求 \(n+1\) 組,就需要 \(O(n^2)\) 的時間,FFT就是巧妙選擇了有特殊性質的x代入,使得算法變成 \(O(nlogn)\)

根據玄學的歐拉定理得知:
n次單位根 \(wn=e^{2\pi i/n}\)

再用上一些奇怪的定理:
消去定理 \(W_{ak}^{bk}=(e^{i*2kπ/ak})^{bk}=e^{i*2kπ*bk/ak}=e{i*2kπ*b/a}=W_{a}^{b}\)
折半定理 \((W_{n}^{k})^2=e{2*2kπ/n}=e^{2kπ/(n/2)}=W_{n/2}{k}\)

另外就是對稱關係:
\[w_{n}^{n/2+k}=w_{n}^{k} w_{n}^{n/2}=-w_{n}^{k}\]

所以我們就可以把項分類爲奇數次項和偶數次項:
\(A0(x)=a0+a2x+a4x^2+...+a_{n-2}x^{(n-2)/2}\)
\(A1(x)=a1+a3x+a5x^2+...+a_{n-1}x^{(n-1)/2}\)

推出公式:

就可以遞歸處理了

IDFT

結論:直接把相乘後的點值多項式,代入 \(w_{n}^{-1}\) 再做一遍就可以變回係數表示了

遞歸版(常數巨大):

#include<complex>
typedef complex<double>dob;
const double pi=acos(-1.0);
const int N=4000005;
int n,m;
dob a[N],b[N];

inline void FFT(dob *A,int len,int o){
    if(len==1)return ;
    dob wn(cos(2.0*pi/len),sin(2.0*pi*o/len)),w(1,0),t;
    dob A0[len>>1],A1[len>>1];
    for(RG int i=0;i<(len>>1);i++)A0[i]=A[i<<1],A1[i]=A[i<<1|1];
    FFT(A0,len>>1,o);FFT(A1,len>>1,o);
    for(RG int i=0;i<(len>>1);i++,w*=wn){
        t=w*A1[i];
        A[i]=A0[i]+t;
        A[i+(len>>1)]=A0[i]-t;
    }
}

void work()
{
    int x;
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)scanf("%d",&x),a[i]=x;
    for(int i=0;i<=m;i++)scanf("%d",&x),b[i]=x;
    m+=n;
    for(n=1;n<=m;n<<=1);
    FFT(a,n,1);FFT(b,n,1);
    for(int i=0;i<=n;i++)a[i]*=b[i];
    FFT(a,n,-1);
    for(int i=0;i<=m;i++)printf("%d ",int(a[i].real()/n+0.5));
}

int main()
{
    work();
    return 0;
}

非遞歸版

inline void FFT(dob *A,int o){
    for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]);
    for(int i=1;i<n;i<<=1){
        dob wn(cos(pi/i),sin(o*pi/i)),x,y;
        for(int j=0;j<n;j+=(i<<1)){
            dob w(1,0);
            for(int k=0;k<i;k++,w*=wn){
                x=A[j+k];y=w*A[j+i+k];
                A[j+k]=x+y;
                A[j+k+i]=x-y;
            }
        }
    }
}
void priwork(){
    for(n=1;n<=m;n<<=1)L++;
    for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
    FFT(a,1);FFT(b,1);
    for(int i=0;i<=n;i++)a[i]*=b[i];
    FFT(a,-1);
}

快速數論變換

有些題目要求答案要對一個質數取模,用 \(FFT\) 做有些缺陷了
那麼就可以用原根代替單位復根
代碼實現差不多

inline void NTT(int *A,int o){
    for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]);
    for(int i=1;i<n;i<<=1){
        int t0=qm(3,(mod-1)/(i<<1)),x,y;
        for(int j=0;j<n;j+=(i<<1)){
            int t=1;
            for(int k=0;k<i;k++,t=1ll*t0*t%mod){
                x=A[j+k];y=1ll*A[i+j+k]*t%mod;
                A[j+k]=(x+y)%mod;A[j+k+i]=(x-y+mod)%mod;
            }
        }
    }
    if(o==-1)reverse(A+1,A+n);
}
inline void mul(int *A,int *B){
    NTT(A,1);NTT(B,1);
    for(int i=0;i<=n;i++)A[i]=1ll*A[i]*B[i]%mod;
    NTT(A,-1);
    int inv=qm(n,mod-2);
    for(int i=0;i<=n;i++)A[i]=1ll*A[i]*inv%mod;
}

但是這個東西有着極大的缺陷:模數必須是費馬質數(\(P-1\) 有超過序列長度的 \(2\) 的冪因子的質數)
幾個常用的: \(998244353,1004535809,469762049\)
如果模數不是費馬質數也有一個套路:
選擇若干個乘積大於 \(P^2*n\) 的費馬質數取模,最後 \(CRT\) 合併一下

快速沃爾什變化

用處

\(a[i]=\sum a[j]*a[k]\,\,j\bigoplus k=i​\)

三種卷積的求法

正向:
\(xor\)卷積: \(A[j+k]=x+y,A[j+k+i]=x-y\)
\(and\)卷積: \(A[j+k]=x+y\)
\(or\)卷積: \(A[j+k+i]=x+y\)

逆向:
\(xor\)卷積: \(A[j+k]=\frac{x+y}{2},A[j+k+i]=\frac{x-y}{2}\)
\(and\)卷積: \(A[j+k]=x-y\)
\(or\)卷積: \(A[j+k+i]=y-x\)

\(xor\)卷積的模板:

inline void fwt(int *A,int o){
    for(int i=1;i<m;i<<=1)
        for(int j=0;j<m;j+=i<<1)
            for(int k=0;k<i;k++){
                int x=A[j+k],y=A[j+k+i];
                if(!o)A[j+k]=(x+y)%mod,A[j+k+i]=(x-y+mod)%mod;
                else A[j+k]=(x+y)*inv[2]%mod,A[j+k+i]=(x-y+mod)*inv[2]%mod;
            }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章