题目大意:方程 a*x1^2+b*x2^2+c*x3^2+d*x4^2=0
a,b,c,d的范围为[-50,50] , x1,x2,x3,x4的范围为[-100,100].
现给出a,b,c,d,求x1,x2,x3,x4的解的个数.
思路:先求a*x1^2+b*x2^2 所有的值,保存于哈希表中。再查找-(c*x3^2+d*x4^2)是否保存于哈希表中。
问题是解决哈希表中的冲突
线性探测再散列技术
即:当 h(k)位置已经存储有元素的时候,依次探查 (h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中, S为 数组长度。
特别地,如果将数组扫描一圈仍未发现空单元,则说明哈希表已满,这会带来麻烦,但是,该情况完全可以通过扩大数组范围来避免。
看了别人的代码自己重新写了一遍,46ms。学习了。
#include using namespace std; const int MAXN=20021; //ax1^2+bx2^2 和 cx3^2+dx4^2分别最多有10000种可能 int hash[MAXN],counter[MAXN]; //确定在哈希表中位置 ,处理冲突 int hash_fun(int num) { int t; t=num%MAXN; if(t<0) t+=MAXN; while(counter[t] && hash[t]!=num) //当哈希表内已保存 且保存的数之前未出现过 t=(t+ 1)%MAXN; return t; } int main() { int i,j,t,num,ans; int a,b,c,d; int square[101]; for(i=1;i<=100;i++) square[i]=i*i; while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF) { if((a>0 && b>0 && c>0 && d>0) || (a<0 && b<0 && c<0 && d<0)) { printf("0/n"); continue; } memset(counter,0,sizeof(counter)); for(i=1;i<=100;i++) for(j=1;j<=100;j++) { num=a*square[i]+b*square[j]; t=hash_fun(num); hash[t]=num; counter[t]++; } for(i=1,ans=0;i<=100;i++) for(j=1;j<=100;j++) { num=-1*(c*square[i]+d*square[j]); t=hash_fun(num); ans+=counter[t]; } ans*=16; //x1,x2,x3,x4不同的正负 printf("%d/n",ans); } return 0; }