Luogu-T157094 [RC-04] Producto subintegrado (mochila)

Portal de temas

Inserte la descripción de la imagen aquí

Ideas

  • El problema es encontrar el número de más que M. Se siente que el producto mayor que M puede ser muy grande, lo cual no es fácil de manejar. Puede considerar convertirlo en el número de subconjuntos cuyo producto sea menor o igual a METRO. (Réstelo del número total de subconjuntos 2 ^ N)
  • Considere la mochila, de modo que f[x]el representante sea igual al producto del xnúmero de subconjuntos para ser un elemento más dentro de cada matriz de actualización dp nuevamente.
    La violencia inicial se ve así, independientemente del espacio y el tiempo, está en el nivel del cuadrado.
for (i=1; i<=N; i++)	//前 i 个元素
	for (j=1; j<=M; j++)	//乘积为 j
		f[i][j]=f[i-1][j]+f[i-1][j/a[i]];
  • Piense en dónde optimizar. En primer lugar, en realidad hay muy pocos elementos que deben modificarse cada vez. Puede considerar solo el j que debe modificarse; en segundo lugar, debido a que es un conjunto múltiple, puede considerar fusionar y procesando elementos del mismo valor; además de operaciones similares a la matriz rodante, existe el siguiente código.

Código:

#include <cstdio>
#include <cstring>
#define Ha 998244353
#define Max 1000000
typedef long long LL;
using namespace std;

LL N,M,c[Max+5],f[Max+5],a[Max+5],b[Max+5],ans,ss;
LL jc[1000005];

LL ksm(LL x,LL n)
{
    
    
	LL ret=1;
	for (LL i=1,tmp=x; n; ) {
    
    
		if (n&i) {
    
    
			ret=ret*tmp%Ha;
			n^=i;
		}
		tmp=tmp*tmp%Ha;
		i<<=1;
	}
	return ret;
}

LL C(LL x,LL y)
{
    
    
	LL ret=jc[x];
	ret=ret*ksm(jc[y],Ha-2)%Ha;
	ret=ret*ksm(jc[x-y],Ha-2)%Ha;
	return ret;
}

int main()
{
    
    
	
	jc[0]=jc[1]=1;
	for (LL i=2; i<=1000000; i++) jc[i]=jc[i-1]*i%Ha;

	scanf("%lld%lld",&N,&M);
	for (LL i=1; i<=N; i++){
    
    
		scanf("%lld",&a[i]);
		c[a[i]]++;
	}
	
	f[1]=ksm(2,c[1]);
	for (LL i=2,cc,nn=N; i<=Max && nn; i++){
    
    	//元素是 i 的 
		for (LL k=i,tmp=1; k<=M && tmp<=c[i]; k=k*i,tmp++){
    
    		//选 tmp 个 i 
			cc=C(c[i],tmp);		//组合数 
			for (LL j=M/k; j; j--){
    
    
				b[j*k]=(b[j*k]+f[j]*cc)%Ha;		//dp 
			}
		}
		for (LL j=M/i; j; j--){
    
    	//清空临时改变量数组 
			f[j*i]=(f[j*i]+b[j*i])%Ha;
			b[j*i]=0;
		}
		nn-=c[i];
	}
	
	for (LL i=1; i<=M; i++)
		ss=(ss+f[i])%Ha;
	
	ans=ksm(2,N);
	ans-=ss;
	ans=(ans%Ha+Ha)%Ha;
	
	printf("%lld",ans);
	return 0;
}
/*
5 5
1 2 1 2 2
*/

Supongo que te gusta

Origin blog.csdn.net/jackypigpig/article/details/111756887
Recomendado
Clasificación