51nod1769 Clarke and math 2

题目
实际上就是要求\(f*I^k\)
因为\(I^k\)是一个积性函数,所以我们只需要考虑如何求\(I^k(p^a)\)
把这个东西转化成一个长度为\(k\)的序列,每一位是\(\frac{i_k}{i_{k-1}}\),这东西就变成了长度为\(k\)的值域为\([0,a]\)的单调不降序列的方案数,也就是把 \(a\)个球放入\(k\)个盒子里的方案数,即\(a+k-1\choose a\)

#include<bits/stdc++.h>
using namespace std;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
const int N=500007,P=1000000007;
int inc(int a,int b){a+=b;return a>=P? a-P:a;}
int mul(int a,int b){return 1ll*a*b%P;}
int f[N],g[N],x[N],v[N],inv[21],C[21];char s[N<<1];
int main()
{
    int n=read(),i,j,k=0,num;scanf("%s",s+1);
    for(i=1;i<=n;++i) f[i]=read();
    for(i=1;i<=strlen(s+1);++i) k=inc(mul(k,10),s[i]-48);
    for(inv[0]=inv[1]=1,i=2;i<=20;++i) inv[i]=mul(P-P/i,inv[P%i]);
    for(i=1;i<=20;++i) inv[i]=mul(inv[i-1],inv[i]);
    for(i=0;i<=20;++i) for(C[i]=inv[i],j=0;j<i;++j) C[i]=mul(C[i],i+k-j-1);
    for(i=1;i<=n;++i) v[i]=1,x[i]=i;
    for(i=2;i<=n;++i) if(x[i]^1) for(j=i;j<=n;v[j]=mul(v[j],C[num]),j+=i) for(num=0;!(x[j]%i);++num) x[j]/=i;
    for(i=1;i<=n;++i) for(j=i;j<=n;j+=i) g[j]=inc(g[j],mul(f[i],v[j/i]));
    for(i=1;i<=n;++i) printf("%d ",g[i]);
}

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/11723179.html