日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

#3771. Triple 生成函数 + FFT + 容斥

發布時間:2023/12/4 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 #3771. Triple 生成函数 + FFT + 容斥 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

文章目錄

  • 題意:
  • 思路:

題意:

思路:

注意到這個題是求若干個數的組合數,(a,b),(b,a)(a,b),(b,a)(a,b),(b,a)視為一種方案,所以我們考慮生成一個普通型生成函數。
考慮到每個數只能選一次,但是如果我們生成函數相乘的話是不能控制每個數選多少次的,可以簡單腦補一下兩個循環相乘,得到的結果。由于選的物品最多有三個,所以我們考慮分開討論。
我們構造函數a(x)a(x)a(x)表示每個物品選一次,b(x)b(x)b(x)表示每個物品選兩次,c(x)c(x)c(x)表示每個物品選三次。
(1)(1)(1)對于只選一個物品,答案直接為a(x)a(x)a(x)即可。
(2)(2)(2)對于選了兩個物品的情況,我們如果直接計算a2(x)a^2(x)a2(x)的話會發現有重復的部分,這個重復的部分就是每個數選了兩次,所以要減去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)對于選了三個物品的情況,直接計算a3(x)a^3(x)a3(x)也是有很多重復的,考慮從三個中選兩個相同的位置,這個時候方案數即為(32)?a(x)?b(x)\binom{3}{2}*a(x)*b(x)(23?)?a(x)?b(x),再考慮從三個中選三個相同的位置,由于剛才已經減去了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卷一下求答案即可。

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #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;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }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() { // ios::sync_with_stdio(false); // cin.tie(0);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; }

總結

以上是生活随笔為你收集整理的#3771. Triple 生成函数 + FFT + 容斥的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。