Reunión de elogios de la pradera verde

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;
}

Supongo que te gusta

Origin www.cnblogs.com/With-penguin/p/12707496.html
Recomendado
Clasificación