codeforces gym102471 C Dirichlet k-th root

题目:

g=fkg=f^k,其中这里的乘指的是狄利克雷乘积。
现在,已知g求f(f不一定为积性函数)

题解:

g(n)=fk(n)g(n)=f^k(n)
对于这种公式,首先我们应该想到两种方法,
一种是g1k(n)=f(n)g^{\frac{1}{k}}(n)=f(n),对于这种方法只要找到合适的数进行类似快速幂的卷积即可
另一种则是从公式推导,不过不变的肯定是用类似快速幂的思路将k优化到log(k)。
公式推导如下:
设$$F^k(n,m)=\sum_{a_1a_2…*a_k=n,a_i<m}f(a1)f(a2)…*f(ak)$$

g(n)=fk(n)=kf(n)+Fk(n,n)g(n)=f^k(n)=k*f(n)+F^k(n,n)

kf(n)=g(n)Fk(n,n)k*f(n)=g(n)-F^k(n,n)

因此我们只要知道了Fk(n,n)F^k(n,n)就能把f(n)f(n)求出来了。

F2k(n)=dn,if(k==1)1<d<nFk(d)Fk(nd)F^{2k}(n)=\sum_{d|n,if( k==1)1<d<n}{F^{k}(d)F^{k}(\frac{n}{d} )}

F2k+1(n)=dn,dnf(d)F2k(nd)F^{2k+1}(n)=\sum_{d|n,d\neq n}{f(d)F^{2k}(\frac{n}{d} )}

由于在算f(n)f(n)之前,f(1)f(1)f(n1)f(n-1)已经计算出来了所以可以有类似dp转移进行递推

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
const int mod=998244353;
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
#define rint register int
typedef long long ll;
typedef double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
ll qpow(ll a,ll b){ll ans=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)ans=ans*a%mod;a=a*a%mod;}return ans;}
ll gcd(ll a,ll b){return b>0?gcd(b,a%b):a;}
int n,m,T;
int g[maxn],nxt[maxn];
int f[maxn];
vi v[maxn];
int cnt;


int F[65][maxn];

int main() {
//	read(n),read(m);
	scanf("%d%d",&n,&m);
//	n=1e5;
//	m=(1<<29)-1;
	for(int i=2;i<=n;++i){
		for(rint j=i+i;j<=n;j+=i){
			v[j].pb(i);
		}
	} 
//	for(int i=1;i<=n;++i) g[i]=i;
//	for(rint i=1;i<=n;++i) read(g[i]);
	for(int i=1;i<=n;i++) scanf("%d",&g[i]); 
	int inv=qpow(m,mod-2);
	f[1]=1;
	int temp=m;
	int tot=0;
	while(temp){
		nxt[++tot]=temp;
		if(temp&1){
			--temp;
		}else{
			temp>>=1;
		}
	}
	
	
	int res=0;
	for(int i=1;i<=tot;i++) F[i][1]=1;
	for(int i=2;i<=n;++i){
		for(int t=tot-1;t>=1;--t){
			res=0;
			for(int x:v[i]){
				if(nxt[t]&1){
					res=(res+1ll*F[t+1][x]*f[i/x])%mod;
				}else{
					res=(res+1ll*F[t+1][x]*F[t+1][i/x])%mod;
				}
			}
			if(nxt[t]&1){
				res=(res+1ll*F[t+1][i]*f[i/i]%mod)%mod;
			}else{
				res=(res+2ll*F[t+1][i]*F[t+1][i/i]%mod)%mod;
			}
			F[t][i]=res;
		}
		f[i]=(1ll*g[i]-F[1][i]+mod)%mod;
		f[i]=1ll*f[i]*inv%mod;
		F[tot][i]=f[i];
		for(int t=tot-1;t>=1;t--){
			F[t][i]=(F[t][i]+1ll*nxt[t]*f[i]%mod)%mod;
		}
	}
	for(int i=1;i<=n;++i){
//		print(f[i]);
//		print(" ");
		printf("%d%c",f[i]," \n"[i==n]);
	}
//	cout<<cnt<<"\n";
	return 0;
}
/*
5 10000
1 40000 20000 799970000 30000
1 12 6 63 9
5 4
1 16 8 116 12
*/

Q.E.D.