题目大意:
给定两个长为n的数列F和B,求长为n的数列x,使得
∀i∈ [1,n],∑nj=1F(gcd(i,j)) xj=Bi
∀
i
∈
[
1
,
n
]
,
∑
j
=
1
n
F
(
g
c
d
(
i
,
j
)
)
x
j
=
B
i
在模998244353意义下成立。
n≤105
n
≤
10
5
题解:
考虑令
F(n)=∑d|nf(d)
F
(
n
)
=
∑
d
|
n
f
(
d
)
,那么
f(n)=F(n)−∑d|n,d≠nf(d)
f
(
n
)
=
F
(
n
)
−
∑
d
|
n
,
d
≠
n
f
(
d
)
,因此可以再
O(nlgn)
O
(
n
l
g
n
)
时间内通过
F(n)
F
(
n
)
求出
f(n)
f
(
n
)
。
将题目中的F改写成f,有:
∀i∈ [1,n],∑nj=1∑d|i,d|jf(d) xj=Bi
∀
i
∈
[
1
,
n
]
,
∑
j
=
1
n
∑
d
|
i
,
d
|
j
f
(
d
)
x
j
=
B
i
∀i∈ [1,n],∑d|if(d)∑nd|j xj=Bi
∀
i
∈
[
1
,
n
]
,
∑
d
|
i
f
(
d
)
∑
d
|
j
n
x
j
=
B
i
记
x(n)=∑n|dxd
x
(
n
)
=
∑
n
|
d
x
d
,那么
xn=x(n)−∑n|d,n≠dxd
x
n
=
x
(
n
)
−
∑
n
|
d
,
n
≠
d
x
d
,因此知道x(n)后可以
O(nlgn)
O
(
n
l
g
n
)
时间内求出
xn
x
n
。
∀i∈ [1,n],∑d|if(d)x(d)=Bi
∀
i
∈
[
1
,
n
]
,
∑
d
|
i
f
(
d
)
x
(
d
)
=
B
i
∀i∈ [1,n],∑d|ih(d)=b(i)
∀
i
∈
[
1
,
n
]
,
∑
d
|
i
h
(
d
)
=
b
(
i
)
根据上文结论,知道
b(n)
b
(
n
)
之后可以
O(nlgn)
O
(
n
l
g
n
)
时间内求出
h(n)
h
(
n
)
,进而求出
x(n)
x
(
n
)
,进而求出
xn
x
n
具体来说,以已知
F
F
求,代码大致如下:
for(int i=1;i<=n;i++) f[i]=F[i];
for(int i=1;i<=n;i++)
for(int j=i<<1;j<=n;j++)
f[j]-=f[i];
另一个同理。
代码:
// luogu-judger-enable-o2
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100010
#define mod 998244353
#define lint long long
#define gc getchar()
using namespace std;
int f[N],x[N],fi[N];
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int mol(int x) { return x%=mod,(x<0?x+=mod:x); }
inline int fast_pow(int x,int k=mod-2,int ans=1)
{ for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int getf(int *f,int n)
{
for(int i=1;i<=n;i++)
for(int j=i<<1;j<=n;j+=i) f[j]=mol(f[j]-f[i]);
return 0;
}
inline int getg(int *g,int n)
{
for(int i=n;i>=1;i--)
for(int j=i<<1;j<=n;j+=i) g[i]=mol(g[i]-g[j]);
return 0;
}
int main()
{
int n=inn();
for(int i=1;i<=n;i++) f[i]=inn();getf(f,n);
for(int i=1;i<=n;i++) fi[i]=fast_pow(f[i]);
for(int i=1;i<=n;i++) x[i]=inn();getf(x,n);
for(int i=1;i<=n;i++) x[i]=(lint)x[i]*fi[i]%mod;
getg(x,n);for(int i=1;i<=n;i++) printf("%d ",x[i]);
return !printf("\n");
}