题解:mex times mex(省选模拟赛 T2)
前言
题目链接:here.
这是一个 T1 读错题刚 T2 导致垫底的可怜人的博客。
思路分析
首先这个柿子一看就是魔改的 FWT 的卷积。
考虑分治处理。
对于当前分治层 \(A*B=C\),考虑求出 \(C\)。
如果我们将 \(A,B,C\) 三个序列都分为 \(3\) 段,分别记为 \(A_0,A_1,A_2,B_0,B_1,B_2,C_0,C_1,C_2\),那么我们需要通过若干次卷积用 \(A,B\) 求出 \(C\)。
因为 FWT 是线性变换,大胆猜测,我们题目中要求的卷积也是线性变换。
如果有这个性质就好做了,我们只需要构造若干参数,使得用 \(A_0,A_1,A_2,B_0,B_1,B_2\) 中的若干向量卷积能够凑出 \(C_0,C_1,C_2\) 即可。
考虑不要脸地用 \(n=1\) 和 \(n=3\) 的递归关系构造参数。
当 \(n=1\) 时,\(c_0=a_0b_0\)
当 \(n=3\) 时,\(c_0=a_1b_1+a_1b_2+a_2b_1+a_2b_2\),\(c_1=a_0b_2+a_2b_0\),\(c_2=a_0b_1+a_1b_0\)
不难构造出我们想要的参数,也就是:
\[C_0=(A_1+A_2)*(B_1+B_2)
\]
\[C_1=(A_0+A_2)*(B_0+B_2)-A_2*B_2
\]
\[C_2=(A_0+A_1+A_2)*(B_0+B_1+B_2)-C_0-C_1
\]
现在分析复杂度。
设 \(T(n)\) 表示对长度为 \(n\) 的两个序列做卷积的复杂度,那么有递推式:
\[T(n)=4T(\frac{n}{3})+O(n)
\]
大概就是一个 \(O(4^k)\) 罢!
代码实现
#include<bits/stdc++.h>
using namespace std;
int n,k;
inline vector<long long> mex(vector<long long> &a,vector<long long> &b){
int n=a.size();
vector<long long> c(n,1);
if(n==1){
c[0]=a[0]*b[0];
return c;
}
n/=3;
vector<long long> A(n,1),B(n,1);
for(int i=0;i<n;i++){
A[i]=a[i+n*2];
B[i]=b[i+n*2];
}
vector<long long> d1=mex(A,B);//a2*b2
for(register int i=0;i<n;i++){
A[i]+=a[i];
B[i]+=b[i];
}
vector<long long> d2=mex(A,B);//(a0+a2)*(b0+b2)
for(register int i=0;i<n;i++){
A[i]+=a[i+n];
B[i]+=b[i+n];
}
vector<long long> d3=mex(A,B);//(a0+a1+a2)*(b0+b1+b2)
for(register int i=0;i<n;i++){
A[i]-=a[i];
B[i]-=b[i];
}
vector<long long> d4=mex(A,B);//(a1+a2)*(b1+b2)
for(register int i=0;i<n;i++){
c[i]=d4[i];
c[i+n]=d2[i]-d1[i];
c[i+n*2]=d3[i]-d4[i]-d2[i]+d1[i];
}
return c;
}
signed main(){
freopen("mex.in","r",stdin);
freopen("mex.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>k;
n=1;
for(int i=1;i<=k;i++) n*=3;
vector<long long> a(n,1),b(n,1),c(n,1);
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
}
c=mex(a,b);
for(int i=0;i<n;i++){
cout<<c[i]<<' ';
}
return 0;
}