人,只有自己站起来,这个世界才能属于他。|

园龄:粉丝:关注:

题解:mex times mex(省选模拟赛 T2)

前言

题目链接:here.

这是一个 T1 读错题刚 T2 导致垫底的可怜人的博客。

思路分析

首先这个柿子一看就是魔改的 FWT 的卷积。

考虑分治处理。

对于当前分治层 AB=C,考虑求出 C

如果我们将 A,B,C 三个序列都分为 3 段,分别记为 A0,A1,A2,B0,B1,B2,C0,C1,C2,那么我们需要通过若干次卷积用 A,B 求出 C

因为 FWT 是线性变换,大胆猜测,我们题目中要求的卷积也是线性变换。

如果有这个性质就好做了,我们只需要构造若干参数,使得用 A0,A1,A2,B0,B1,B2 中的若干向量卷积能够凑出 C0,C1,C2 即可。

考虑不要脸地用 n=1n=3 的递归关系构造参数。

n=1 时,c0=a0b0

n=3 时,c0=a1b1+a1b2+a2b1+a2b2c1=a0b2+a2b0c2=a0b1+a1b0

不难构造出我们想要的参数,也就是:

C0=(A1+A2)(B1+B2)

C1=(A0+A2)(B0+B2)A2B2

C2=(A0+A1+A2)(B0+B1+B2)C0C1

现在分析复杂度。

T(n) 表示对长度为 n 的两个序列做卷积的复杂度,那么有递推式:

T(n)=4T(n3)+O(n)

大概就是一个 O(4k) 罢!

代码实现

#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;
}

本文作者:Kenma

本文链接:https://www.cnblogs.com/Kenma/p/18706548

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Kenma  阅读(28)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起