codeforces gym102471 C Dirichlet k-th root
题目:
有,其中这里的乘指的是狄利克雷乘积。
现在,已知g求f(f不一定为积性函数)
题解:
有
对于这种公式,首先我们应该想到两种方法,
一种是,对于这种方法只要找到合适的数进行类似快速幂的卷积即可
另一种则是从公式推导,不过不变的肯定是用类似快速幂的思路将k优化到log(k)。
公式推导如下:
设$$F^k(n,m)=\sum_{a_1a_2…*a_k=n,a_i<m}f(a1)f(a2)…*f(ak)$$
因此我们只要知道了就能把求出来了。
由于在算之前,到已经计算出来了所以可以有类似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.