My Blogs
[ARC182C] Sum of Number of Divisors of Product
見過一萬遍的套路啊啊啊啊啊。
首先如果序列乘積是 \(\prod c_i^{p_i}\),答案就是 \(\prod (p_i+1)\)。\(M\) 以內的質數個數只有 \(6\) 個:\(\{2,3,5,7,11,13\}\)。
然後考慮這個式子的組合意義:對於每個質因子,可以看成在其每次出現的時候可以選它,這樣每個質因子需要恰好被選一次。對於 \(+1\) 的問題可以一開始就把所有無論選還是不選的答案設成 \(1\)。
狀壓上面這個東西,\(0\) 表示這一位還沒選,\(1\) 表示選了。預處理轉移矩陣,因為要求序列長度 \(\leq n\),所以還要開一維記答案,總複雜度 \(\mathcal O((2^6+1)^3\log n)\)。
int n,m,v[6];
struct Matrix{int f[65][65];Matrix(){memset(f,0,sizeof(f));}}M;
struct Vector{int f[65];Vector(){memset(f,0,sizeof(f));}}F;
inline Matrix operator *(const Matrix x,const Matrix y)
{
Matrix z;
for(int i=0;i<65;++i)for(int j=0;j<65;++j)for(int k=0;k<65;++k)
Madd(z.f[i][j],Cmul(x.f[i][k],y.f[k][j]));
return z;
}
inline Vector operator *(const Vector x,const Matrix y)
{
Vector z;
for(int j=0;j<65;++j)for(int k=0;k<65;++k)
Madd(z.f[j],Cmul(x.f[k],y.f[k][j]));
return z;
}
const int P[6]={2,3,5,7,11,13};
inline void mian()
{
read(n,m),M.f[64][64]=1;
for(int i=1;i<=m;++i)
{
int x=i;memset(v,0,sizeof(v));
for(int j=0;j<6;++j)while(x%P[j]==0)++v[j],x/=P[j];
for(int j=0;j<64;++j)
{
for(int k=j;;k=(k-1)&j)
{
int s=1;
for(int l=0;l<6;++l)if((k^j)>>l&1)Mmul(s,v[l]);
Madd(M.f[k][j],s);
if(j==63)Madd(M.f[k][64],s);
if(!k)break;
}
}
}
for(int i=0;i<64;++i)F.f[i]=1;
for(;n;n>>=1,M=M*M)if(n&1)F=F*M;
write(F.f[64]);
}