【51Nod1769】Clarke and math2(數論,組合數學)

【51Nod1769】Clarke and math2(數論,組合數學)

題面

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;
}
相關文章
相關標籤/搜索