题解: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;
}
posted @ 2025-02-09 19:46  _Kenma  阅读(36)  评论(0编辑  收藏  举报