Problem
一句话题意
给定f,求g,我们定义
g(i)=∑i1|i∑i2|i1∑i3|i2…∑ik|ik−1f(ik)mod1000000007
g
(
i
)
=
∑
i
1
|
i
∑
i
2
|
i
1
∑
i
3
|
i
2
…
∑
i
k
|
i
k
−
1
f
(
i
k
)
mod
1000000007
Solution
用Dirichlet卷积进行优化,Dirichlet卷积的定义是这样的
(f∗g)(n)=∑d|nf(d)g(nd)
(
f
∗
g
)
(
n
)
=
∑
d
|
n
f
(
d
)
g
(
n
d
)
观察由g到f的计算式,不难看出就是每一层求和就是一次迭代。
我们令 I I 为单位元。
当k=1时,我们有
同样的,当k=2时,我们有
g2(i)=∑j|i∑d|jf(d)∗1=∑j|ig1(j)∗1⇔g2=(I∗(f∗I))
g
2
(
i
)
=
∑
j
|
i
∑
d
|
j
f
(
d
)
∗
1
=
∑
j
|
i
g
1
(
j
)
∗
1
⇔
g
2
=
(
I
∗
(
f
∗
I
)
)
所以题中所求就相当于
gk=(f∗Ik)
g
k
=
(
f
∗
I
k
)
行末不要输出多余的空格,会卡格式!
Code
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=100010,mod=1000000007;
int z,n,k,f[maxn],g[maxn],tmp[maxn];
inline void pls (int &x){if(x>=mod) x-=mod;}
void mul(int *a,int *b)
{
for(int i=1;i<=n;i++) tmp[i]=0;
for(int i=1;i<=n;i++)
for(int j=1;i*j<=n;j++)
pls(tmp[i*j]+=(ll)a[i]*b[j]%mod);
for(int i=1;i<=n;i++) a[i]=tmp[i];
}
int main()
{
scanf("%d",&z);
while(z--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&g[i]),f[i]=1;
for(;k;k>>=1,mul(f,f))
if(k&1)
mul(g,f);
for(int i=1;i<n;i++) printf("%d ",g[i]);
printf("%d\n",g[n]);
}
return 0;
}