【大意】
给定 (n) 和三个下标从 (1) 开始,长度为 (n) 的数列 (a, b, c)
对于整数 (p), 我们构造数列 (displaystyle d_{p,k}=sum_{iotimes j=k}a_ib_j(1leq i, jleq{nover p}))
其中,位运算 (iotimes j) 表示 (i) 与 (j) 在三进制意义下按位取 (gcd),即 (k_t=gcd(i_t, j_t))
现要求求出 (displaystyle sum_{p=1}^nsum_{k=1}^{+infty} d_{p, k}cdot c_p^k)
【分析】
比较显然的广义FWT
前置推导知识参考本人博客 关于 FWT 的一些理解
需要构造三阶方阵使得 (T_{C(n, gcd(p,q)} )=T_{A(n, p)}T_{B(n, q)})
由于为三进制,故仅需寻找一种构造,使得:
(T_C=left( egin{matrix} T_{C(0,0)}&T_{C(0,1)}&T_{C(0,2)} \\ T_{C(1,0)}&T_{C(1,1)}&T_{C(1,2)} \\ T_{C(2,0)}&T_{C(2,1)}&T_{C(2,2)} end{matrix} ight)) 为可逆矩阵即可
具体推导过程见后文,这里直接给出一组解: (T_A=T_B=T_C=left( egin{matrix} 1&0&0 \\ 1&1&1 \\ 1&0&1 end{matrix} ight)) ,逆矩阵 (T_C^{-1}=left( egin{matrix} 1&0&0 \\ 0&1&-1 \\ -1&0&1 end{matrix} ight))
由此,对 (a,b) 的前 ({nover p}) 项提取出来,进行 FWT 变换为 (T_Aa,T_Bb) 后直接点积,求出 (T_Cd)
再由 (d=T_C^{-1}cdot T_Cd) 进行 UFWT 求出 (d) 数列
之后由秦九韶定理,可以 (O({nover p})) 直接跑出第二个求和符号内的结果
总时间复杂度为 (displaystyle T(n)=sum_{p=1}^n[O({nover p}log{nover p})+O({nover p})]=O(nlog^2 n))
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
typedef double db;
#define fi first
#define se second
const int MOD=1e9+7, MAXN=6e5+10;
inline int add(int a, int b) { return (a+=b)>=MOD?a-MOD:a; }
inline int dis(int a, int b) { return (a-=b)<0?a+MOD:a; }
int n, a[MAXN], b[MAXN], c[MAXN], d[MAXN], aa[MAXN], bb[MAXN];
inline void exFWT(int *a, int N, int flag){
for(int i=1;i<N;i*=3) for(int S=0; S<N; ++S)
if( (S/i)%3==0 ){
int x=a[S], y=a[S+i], z=a[S+i+i];
if(!flag){
a[S+i+i]=add(x, z);
a[S+i]=add(a[S+i+i], y);
a[S]=x;
}
else{
a[S]=x;
a[S+i]=dis(y, z);
a[S+i+i]=dis(z, x);
}
}
}
inline int calc(int n, int c){
int N=1;
while(N<=n) N*=3;
for(int i=0;i<=n;++i) aa[i]=a[i]; for(int i=n+1;i<N;++i) aa[i]=0;
for(int i=0;i<=n;++i) bb[i]=b[i]; for(int i=n+1;i<N;++i) bb[i]=0;
exFWT(aa, N, 0); exFWT(bb, N, 0);
for(int i=0;i<N;++i) d[i]=(ll)aa[i]*bb[i]%MOD;
exFWT(d, N, 1);
int res=0;
for(int i=0, bas=1;i<N;++i, bas=(ll)bas*c%MOD)
res=add(res, (ll)bas*d[i]%MOD);
return res;
}
inline int ans(){
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i) cin>>b[i];
for(int i=1;i<=n;++i) cin>>c[i];
int res=0;
for(int p=n;p>=1;--p)
res=add(res, calc(n/p, c[p]) );
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
while(cin>>n)
cout<<ans()<<"
";
cout.flush();
return 0;
}
【证明】
矩阵推导:
由 (T_{C(n, gcd(p,q)} )=T_{A(n, p)}T_{B(n, q)}) 可发现,每一个 (n) 之间都是独立的,故下文直接使用 (c_{gcd(p, q)},a_p,b_q) 等来简便表示
由 (gcd) 的运算得:
(egin{cases} c_0=a_0cdot b_0 \\ c_1=a_0cdot b_1=a_1cdot b_0=a_1cdot b_1=a_1cdot b_2=a_2cdot b_1 \\ c_2=a_0cdot b_2=a_2cdot b_0=a_2cdot b_2 end{cases})
若要使得 (T_C) 可逆,则 (T_C) 矩阵满秩,故 (c_0,c_1,c_2) 不能同时为 (0)
由 (a_0cdot b_2=a_2cdot b_2) 得 (b_2cdot (a_0-a_2)),故 ((b_2=0)vee (a_0=a_2))
由 (a_2cdot b_0=a_2cdot b_2) 得 ((a_2=0)vee (b_0=b_2))
故 (c_2=a_0cdot b_2=a_2cdot b_0=a_2cdot b_2) 得:
((a_2=b_2=0)vee (b_0=b_2=0)vee (a_0=a_2=0)vee (a_0=a_2wedge b_0=b_2))
由于 (a_0=0vee b_0=0) 时 (c_0=c_1=c_2=0),不满足
故仅解得 ((a_2=b_2=0)vee (a_0=a_2wedge b_0=b_2))
由 (a_0cdot b_1=a_1cdot b_1=a_2cdot b_1) 得 (a_0=a_1=a_2vee b_1=0)
由 (a_1cdot b_0=a_1cdot b_1=a_1cdot b_2) 得 (a_1=0vee b_0=b_1=b_2)
故解得 ((a_0=a_1=a_2=0)vee (a_0=a_1=a_2wedge b_0=b_1=b_2)vee (b_1=a_1=0)vee(b_0=b_1=b_2=0))
同理扣去 (a_0=0) 与 (b_0=0) 的条件
仅解得 ((a_0=a_1=a_2wedge b_0=b_1=b_2)vee(a_1=b_1=0))
联立条件 (a_2=b_2=0) 与 (a_0=a_1=a_2wedge b_0=b_1=b_2) 时,得到 (a_0=b_0=0) ,不合法
联立条件 (a_2=b_2=0) 与 (a_1=b_1=0) 时,得到 (a_1=a_2=0,b_1=b_2=0),代入得到 (c_1=c_2=0,c_0=a_0cdot b_0)
取 (a_0=b_0=1) 得到一组解:(vec a=(1, 0, 0), vec b=(1, 0, 0), vec c=(1, 0, 0))
联立条件 ((a_0=a_2wedge b_0=b_2)) 与 ((a_0=a_1=a_2wedge b_0=b_1=b_2)) 时,得到 (c_0=c_1=c_2=a_0cdot b_0)
取 (a_0=b_0=1) 得到一组解:(vec a=(1, 1, 1), vec b=(1, 1, 1), vec c=(1, 1, 1))
联立条件 ((a_0=a_2wedge b_0=b_2)) 与 (a_1=b_1=0) 时,得到 (c_1=0, c_0=c_2=a_0cdot b_0)
取 (a_0=b_0=1) 得到一组解:(vec a=(1, 0, 1), vec b=(1, 0, 1), vec c=(1, 0, 1))
综上,可构造出矩阵 (T_A=left( egin{matrix} 1&0&0 \\ 1&1&1 \\ 1&0&1 end{matrix} ight), T_B=left( egin{matrix} 1&0&0 \\ 1&1&1 \\ 1&0&1 end{matrix} ight), T_C=left( egin{matrix} 1&0&0 \\ 1&1&1 \\ 1&0&1 end{matrix} ight))
由 ((T_C|E)=left( egin{array}{ccc|ccc} 1&0&0& 1&0&0 \\ 1&1&1& 0&1&0 \\ 1&0&1& 0&0&1 end{array} ight) o left( egin{array}{ccc|ccc} 1&0&0& 1&0&0 \\ 0&1&0& 0&1&-1 \\ 0&0&1& -1&0&1 end{array} ight)=(Emid T_C^{-1}))
得到 (T_C^{-1}=left( egin{matrix} 1&0&0 \\ 0&1&-1 \\ -1&0&1 end{matrix} ight))