Suma estadística - Suma de prefijo

Sobre el tema:

  Dada una matriz de enteros de longitud n y un entero k, debe encontrar el número de subarreglos consecutivos en la matriz que suman k,

Muestra de prueba:

ingresar:

5 3
1 1 2 1 1

producción:

2

  Idea 1:

    Use el ciclo for para enumerar violentamente los subconjuntos y sume + cuente, la complejidad del tiempo es O (n ^ 3). (Si los datos son superiores a 100, esta idea definitivamente es Límite de tiempo excedido (tiempo extra), por lo que debe optimizarse).

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int a[n],sum=0; //定义数组和计数器 
	for(int i=0;i<n;i++) //for循环输入 
	  scanf("%d",a[i]); //输入下标为i的数 
	for(int i=0;i<n;i++){ //区间i枚举 
		for(int j=0;j<n;j++){ //区间j枚举 
			int ans=0; //区间和计数数组 
			for(int x=i;x<=j;x++) //求出区间[i,j]的和 
			  ans+=a[i]; //计数 
			if(ans==k) //比较 
			  sum++; //计数	  
		}
	}
	cout<<sum<<endl; //输出 
	return 0;
}

Idea 2:

  También podemos usar la suma de prefijos para resolver este problema. Primero, preprocesar la suma de la matriz de prefijos de a, calcular la suma de las sub-matrices cada vez, y luego realizar la enumeración de intervalo de doble bucle y luego compararla con k. La complejidad del tiempo es O (n^2) (si los datos no son mayores que 1500, puede ser AC y todavía hay espacio para la optimización).

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans 
	sum[0]=0; //将下标为0的地址初始化为0  
	for(int i=1;i<=n;i++){ //进行循环n次读入 
		int a; //定义 
		scanf("%d",&a); //输入 
		sum[i]=sum[i-1]+a; //求前缀和 
	}
	for(int i=1;i<=n;i++) //区间枚举i 
	  for(int j=0;j<n;j++) //区间枚举j 
	    if(sum[i]-sum[j]==k) //求出区间[i,j]的和与k比较 
	      ans++; //计数器加1 
	cout<<ans<<endl; //输出计数器 
	return 0; //结束 
}

Idea 3:

  Podemos usar map (una clase definida por la biblioteca STL), prefijar y optimizar. En la idea de usar el prefijo sum solo, requerimos si la suma de un subarreglo con el subíndice i al final es k, necesitamos atravesar j de 0 a i-1 para encontrar si hay sum[i] -k= suma[j]. Luego solo usamos map para guardar el prefijo sum de los primeros i elementos, guardar el valor del prefijo sum antes del número de ocurrencias (>i) y finalmente juzgar si el mapa contiene sum[i]-k.

  La complejidad del tiempo es O(n), que ya es muy rápida, y los datos pueden ser AC si son tan grandes como varios millones.

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans 
	sum[0]=0; //将下标为0的地址初始化为0  
	map<int,int> p; //定义map 
	for(int i=1;i<=n;i++){ //进行循环n次读入 
		int a; //定义 
		scanf("%d",&a); //输入 
		sum[i]=sum[i-1]+a; //求前缀和 
		p[sum[i]]++; //进行存储 
	}
	for(int i=0;i<n;i++) //进行区间判断 
	  ans+=p[sum[i]+k]; //计数 
	cout<<ans<<endl; //输出 
	return 0; //结束 
}

Resumir:

  Esta pregunta es clásica en las sumas de prefijos, que es equivalente a un trampolín, y hay diferencias más difíciles, sumas de prefijos bidimensionales, etc.

Supongo que te gusta

Origin blog.csdn.net/wo_ai_luo_/article/details/129820823
Recomendado
Clasificación