复活石

复活石

在这里插入图片描述

题解

很容易看出原式就是一个循环嵌套的过程。
我们设 g k ( i ) = ∑ i k ∣ i g k − 1 ( i k ) g_k(i)=\sum_{i_k|i}g_{k-1}(i_k) gk(i)=ikigk1(ik),其中 g 0 ( i ) = f ( i ) g_0(i)=f(i) g0(i)=f(i)
如果我们直接将其循环 k k k次明显是不行的,但我们很快发现这个式子像多项式一样求,有,
g k = g k − 1 ⋅ f g_k=g_{k-1}\cdot f gk=gk1f
于是,就有
g k = g 0 k ⋅ f g_k=g_0^k\cdot f gk=g0kf
这里的 g 0 g_0 g0就应该是 { 1 , 1 , 1 , . . . } \{1,1,1,...\} {1,1,1,...}
于是,我们直接像快速幂一样跑一下即可。

时间复杂度 O ( T n l o g   n l o g   k ) O\left(Tnlog\,nlog\,k\right) O(Tnlognlogk)

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<time.h>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
typedef long long LL;
typedef unsigned long long uLL;
typedef unsigned int uint;
typedef pair<int,int> pii;
const int INF=0x7f7f7f7f;
const int mo=1e9+7;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int T,n,k,f[MAXN],g[MAXN],h[MAXN];
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
void sakura(int *a,int *b){
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j+=i)
			h[j]=add(h[j],1ll*a[i]*b[j/i]%mo);
	for(int i=1;i<=n;i++)a[i]=h[i],h[i]=0;
}
signed main(){
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	read(T);
	while(T--){
		read(n);read(k);
		for(int i=1;i<=n;i++)read(f[i]),g[i]=1;
		while(k){if(k&1)sakura(f,g);sakura(g,g);k>>=1;}
		for(int i=1;i<=n;i++)printf("%d ",f[i]);puts("");
	}
	return 0;
}




谢谢!!!

posted @ 2021-04-10 12:00  StaroForgin  阅读(104)  评论(0)    收藏  举报  来源