POJ_1840_Eqs (hash)
http://poj.org/problem?id=1940
题意:给一个五元方程的系数,计算满足方程的接的个数。每一个变量的取值范围诗
给出的。
如果单纯枚举的话很容易超时5层循环要执行100^5次。
那么我们来一个变形再用哈希做;
把其中两个变量及系数移到等号另一边,那么执行次数就下降了很多
从O(n^5)->O(n^2+n^3);
我们可以定义一个数组hash[],初始化为零;对于方程左边当
x1和x2确定得到一个值sum的时候那么我们可以用hash[sum]来记录
这个sum。但是这里有一个冲突的问题,例如当x1=5,x2=3;和x1=3,x2=5;这两个
的sum是一样的,这时候我们可以进行hash[sum]++操作。就是记录值是sum的这个解左边有几个
当我们在对右边进行操作的时候,直接cnt+=hash[]即可。
由于x的值能取到负数,但是hash的下标是取不到的,方程左边数据取最大可以得到
50*50^3+50*50^3=12500000,我们可以扩大两倍进行存储;只要遇到sunm<0的就进行
sum=sum+25000000运算。
1 # include <stdio.h> 2 # include <string.h> 3 short hash[25000001];//可以用char,char更省时间,但是不能用int,int4个字节,而short2个字节 4 int main() 5 { 6 int a1,a2,a3,a4,a5; 7 int x1,x2,x3,x4,x5; 8 int i,j,k,sum; 9 10 while(scanf("%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5) != EOF) 11 { 12 memset(hash,0,sizeof(hash)); 13 for(i=-50;i<=50;i++) 14 { 15 if(!i) 16 continue; 17 for(j=-50;j<=50;j++) 18 { 19 if(!j) 20 continue; 21 sum=(a1*i*i*i+a2*j*j*j)*(-1); 22 if(sum<0) 23 sum=sum+25000000; 24 hash[sum]++; 25 } 26 } 27 int cnt=0; 28 for(i=-50;i<=50;i++) 29 { 30 if(!i) 31 continue; 32 for(j=-50;j<=50;j++) 33 { 34 if(!j) 35 continue; 36 for(k=-50;k<=50;k++) 37 { 38 if(!k) 39 continue; 40 sum=a3*i*i*i+a4*j*j*j+a5*k*k*k; 41 if(sum<0) 42 sum=sum+25000000; 43 if(hash[sum]) 44 cnt+=hash[sum]; 45 } 46 } 47 } 48 printf("%d\n",cnt); 49 } 50 return 0; 51 }
优化以后:代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # include <stdio.h> 2 # include <string.h> 3 char hash[25000001]; 4 int main() 5 { 6 int a1,a2,a3,a4,a5; 7 int x1,x2,x3,x4,x5; 8 int i,j,k,sum; 9 int cube[101]; 10 while(scanf("%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5) != EOF) 11 { 12 memset(hash,0,sizeof(hash)); 13 for(i=-50;i<=50;i++) 14 cube[i+50] = i*i*i; 15 for(i=-50;i<=50;i++) 16 { 17 if(!i) 18 continue; 19 for(j=-50;j<=50;j++) 20 { 21 if(!j) 22 continue; 23 sum=(a1*cube[i+50]+a2*cube[j+50])*(-1); 24 if(sum<0) 25 sum=sum+25000000; 26 hash[sum]++; 27 } 28 } 29 int cnt=0; 30 for(i=-50;i<=50;i++) 31 { 32 if(!i) 33 continue; 34 for(j=-50;j<=50;j++) 35 { 36 if(!j) 37 continue; 38 for(k=-50;k<=50;k++) 39 { 40 if(!k) 41 continue; 42 sum=a3*cube[i+50]+a4*cube[j+50]+a5*cube[k+50]; 43 if(sum<0) 44 sum=sum+25000000; 45 if(hash[sum]) 46 cnt+=hash[sum]; 47 } 48 } 49 } 50 printf("%d\n",cnt); 51 } 52 return 0; 53 }
Map做法,原理差不多
1 #include<map> 2 #include<stdio.h> 3 using namespace std; 4 map<int,int> my; 5 int cube[111]; 6 int main(void) 7 { 8 int a[5]; 9 int i; 10 for(i=-50;i<=50;i++) 11 cube[i+50] = i*i*i; 12 for(i=0;i<5;i++) 13 scanf("%d",a+i); 14 int j,k; 15 for(i=-50;i<=50;i++) 16 { 17 if(!i)continue; 18 for(j=-50;j<=50;j++) 19 { 20 if(!j)continue; 21 int result = cube[i+50]*a[3]+cube[j+50]*a[4]; 22 if(my.find(result) != my.end()//这句话的作用是查找result是否在map中出现过。不加的话会超时。 23 my[result]++; 24 else my[result]=1; 25 } 26 } 27 28 int ans = 0; 29 for(i=-50;i<=50;i++) 30 { 31 if(!i)continue; 32 for(j=-50;j<=50;j++) 33 { 34 if(!j)continue; 35 for(k=-50;k<=50;k++) 36 { 37 if(!k)continue; 38 int result = cube[i+50]*a[0]+cube[j+50]*a[1]+cube[k+50]*a[2]; 39 if(my.find(-result) != my.end()) 40 ans += my[-result]; 41 } 42 } 43 } 44 printf("%d\n",ans); 45 return 0; 46 }