Debido a que la percepción del DP del blogger es demasiado baja, no encontró que fuera DP durante el examen. . .
Se encuentra que cada número debe ser un múltiplo del número delante de él, por lo que esta secuencia debe estar ordenada, y no es difícil encontrar que esta secuencia tiene a lo sumo \ (O (logn) \) números diferentes, así que configure \ (f [ i] [j] \) significa que hay \ (i \) números diferentes, y el último número es el número de esquemas de \ (j \) .
Entonces, al final hay \ (d \) números diferentes \ (cnt [d] = \ sum f [d] [j] \) , y luego consideramos poner estos números en longitud \ (n \ ) En la secuencia requerida por el título, desde el principio de la partición en el número combinado, se puede saber que hay \ (d \) tipos de programas con \ (cnt [d] \ times \ tbinom {k-1} {d-1} \ ) , Entonces \ (ans = \ sum_ {d = 1} ^ {log_n} cnt [d] \ times \ tbinom {k-1} {d-1} \) .
El código es el siguiente:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1000009,M=1000000007;
int n,k,a[N],ans,f[25][N],fac[N],invf[N];
void init()
{
scanf("%d %d",&n,&k);
}
void ADD(int &x,int y)
{
x=(x+y)%M;
}
int ksm(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=1LL*res*a%M;
b>>=1,a=1LL*a*a%M;
}
return res;
}
void work()
{
fac[0]=1;
int Q=N-9;
for (int i=1;i<=Q;i++)
fac[i]=1LL*fac[i-1]*i%M;
invf[Q]=ksm(fac[Q],M-2);
for (int i=Q-1;i>=0;i--)
invf[i]=1LL*invf[i+1]*(i+1)%M;
for (int i=1;i<=n;i++)
f[1][i]=1;
for (int i=1;1<<i-1<=n;i++)
for (int j=1;j<=n>>1;j++)
if(f[i][j])
for (int k=j+j;k<=n;k+=j)
ADD(f[i+1][k],f[i][j]);
int ans=0;
for (int i=1;1<<i-1<=n;i++)
{
int tmp=0;
for (int j=1;j<=n;j++)
ADD(tmp,f[i][j]);
ADD(ans,(int)(1LL*tmp*fac[k-1]%M*invf[i-1]%M*invf[k-i]%M));
}
printf("%d\n",ans);
}
int main()
{
init();
work();
return 0;
}