生活随笔
收集整理的這篇文章主要介紹了
#3771. Triple 生成函数 + FFT + 容斥
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
傳送門
文章目錄
題意:
思路:
注意到這個(gè)題是求若干個(gè)數(shù)的組合數(shù),(a,b),(b,a)(a,b),(b,a)(a,b),(b,a)視為一種方案,所以我們考慮生成一個(gè)普通型生成函數(shù)。
考慮到每個(gè)數(shù)只能選一次,但是如果我們生成函數(shù)相乘的話是不能控制每個(gè)數(shù)選多少次的,可以簡單腦補(bǔ)一下兩個(gè)循環(huán)相乘,得到的結(jié)果。由于選的物品最多有三個(gè),所以我們考慮分開討論。
我們構(gòu)造函數(shù)a(x)a(x)a(x)表示每個(gè)物品選一次,b(x)b(x)b(x)表示每個(gè)物品選兩次,c(x)c(x)c(x)表示每個(gè)物品選三次。
(1)(1)(1)對于只選一個(gè)物品,答案直接為a(x)a(x)a(x)即可。
(2)(2)(2)對于選了兩個(gè)物品的情況,我們?nèi)绻苯佑?jì)算a2(x)a^2(x)a2(x)的話會(huì)發(fā)現(xiàn)有重復(fù)的部分,這個(gè)重復(fù)的部分就是每個(gè)數(shù)選了兩次,所以要減去b(x)b(x)b(x),由于其組合有222種,答案即為a2(x)?b(x)2\frac{a^2(x)-b(x)}{2}2a2(x)?b(x)?。
(3)(3)(3)對于選了三個(gè)物品的情況,直接計(jì)算a3(x)a^3(x)a3(x)也是有很多重復(fù)的,考慮從三個(gè)中選兩個(gè)相同的位置,這個(gè)時(shí)候方案數(shù)即為(32)?a(x)?b(x)\binom{3}{2}*a(x)*b(x)(23?)?a(x)?b(x),再考慮從三個(gè)中選三個(gè)相同的位置,由于剛才已經(jīng)減去了333倍的了,所以需要加上2?c(x)2*c(x)2?c(x)。由于各自的組合有666種,所以最終答案為a3(x)?3?a(x)?b(x)+2?c(x)6\frac{a^3(x)-3*a(x)*b(x)+2*c(x)}{6}6a3(x)?3?a(x)?b(x)+2?c(x)?。
直接FFTFFTFFT卷一下求答案即可。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=10000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6,PI
=acos(-1);int n
,m
;
int A
[N
],B
[N
],C
[N
];
int rev
[N
];
int bit
,limit
;struct Complex {double x
,y
;Complex
operator + (const Complex
& t
) const { return {x
+t
.x
,y
+t
.y
}; }Complex
operator - (const Complex
& t
) const { return {x
-t
.x
,y
-t
.y
}; }Complex
operator * (const Complex
& t
) const { return {x
*t
.x
-y
*t
.y
,x
*t
.y
+y
*t
.x
}; }
}a
[N
],b
[N
],c
[N
],ans
[N
];void fft(Complex a
[],int inv
) {for(int i
=0;i
<limit
;i
++) if(i
<rev
[i
]) swap(a
[i
],a
[rev
[i
]]);for(int mid
=1;mid
<limit
;mid
<<=1) {Complex w1
=Complex({cos(PI
/mid
),inv
*sin(PI
/mid
)});for(int i
=0;i
<limit
;i
+=mid
*2) {Complex wk
=Complex({1,0});for(int j
=0;j
<mid
;j
++,wk
=wk
*w1
) {Complex x
=a
[i
+j
],y
=wk
*a
[i
+j
+mid
];a
[i
+j
]=x
+y
; a
[i
+j
+mid
]=x
-y
;}}}
}int main()
{
cin
>>n
;int mx
=0;for(int i
=1;i
<=n
;i
++) {int x
; scanf("%d",&x
);a
[x
].x
++; b
[x
*2].x
++; c
[x
*3].x
++;mx
=max(mx
,x
*3);}while((1<<bit
)<=mx
) bit
++;limit
=1<<bit
;for(int i
=0;i
<limit
;i
++) rev
[i
]=(rev
[i
>>1]>>1)|((i
&1)<<(bit
-1));fft(a
,1); fft(b
,1); fft(c
,1);for(int i
=0;i
<limit
;i
++) {Complex x
={3,0},y
={2,0},z
={1.0/6,0},h
={1.0/2,0};ans
[i
]=ans
[i
]+(a
[i
]*a
[i
]*a
[i
]-x
*a
[i
]*b
[i
]+y
*c
[i
])*z
;ans
[i
]=ans
[i
]+(a
[i
]*a
[i
]-b
[i
])*h
;ans
[i
]=ans
[i
]+a
[i
];}fft(ans
,-1);for(int i
=0;i
<limit
;i
++) {int val
=(int)(ans
[i
].x
/limit
+0.5);if(val
) printf("%d %d\n",i
,val
);}return 0;
}
總結(jié)
以上是生活随笔為你收集整理的#3771. Triple 生成函数 + FFT + 容斥的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。