51Nodhtml
考慮枚舉一個\(i_k\),枚舉一個\(i\),怎麼計算\(i_k\)對\(i\)的貢獻。
把\(\frac{i}{i_k}\)拆掉,維護一個長度爲\(k\)的數組,表示\(\frac{i_{k-1}}{i_{k}}\),對於每個質因子,假設其出現次數爲\(a\),那麼就是把\(a\)個元素放進\(k\)個盒子裏,盒子能夠空,這個的方案數是\({a+k-1\choose k-1}={a+k-1\choose a}\),不難發現\(a\)很小,因此能夠直接\(O(a)\)暴力算。
因而咱們提早對於每個\(a\)算出方案數,而後提早把質因數分解好,就能夠作到\(O(nlogn)\)了。ios
#include<iostream> #include<cstdio> using namespace std; #define MOD 1000000007 #define MAX 500500 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=(x*10ll+ch-48)%MOD,ch=getchar(); return t?-x:x; } int n,K,C[25],f[MAX],g[MAX],x[MAX],v[MAX],inv[25]; int main() { n=read();K=read(); for(int i=1;i<=n;++i)f[i]=read(); inv[0]=inv[1]=1;for(int i=2;i<=20;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD; for(int i=1;i<=20;++i)inv[i]=1ll*inv[i-1]*inv[i]%MOD; for(int a=0;a<=20;++a) { int nw=(a+K-1)%MOD;C[a]=inv[a]; for(int i=0;i<a;++i)C[a]=1ll*C[a]*(nw-i+MOD)%MOD; } for(int i=1;i<=n;++i)x[i]=i,v[i]=1; for(int i=2;i<=n;++i) if(x[i]!=1) for(int j=i;j<=n;j+=i) { int a=0; while(x[j]%i==0)++a,x[j]/=i; v[j]=1ll*v[j]*C[a]%MOD; } for(int i=1;i<=n;++i) for(int j=i;j<=n;j+=i) g[j]=(g[j]+1ll*f[i]*v[j/i])%MOD; for(int i=1;i<=n;++i)printf("%d ",g[i]); puts("");return 0; }