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 }

优化以后:代码 

 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 }
View Code

 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 }

 

posted on 2013-08-21 10:08  随风浪子的博客  阅读(135)  评论(0编辑  收藏  举报

导航