1.题目描述:点击打开链接
2.解题思路:本题利用Hash技术+双向查找解决。可以先计算出a*x0*x0+b*x1*x1的所有可能结果,然后再查找-(c*x2*x2+d*x3*x3)的个数,由于每个值都有2种情况,因此一共有16种组合,最终统计出个数后还要乘以16。存储前一半的所有可能的结果可以有多种方法,可以使用STL中的set或者multiset,也可以自己写一个Hash函数,将所有结果和一个Hash值对应(不一定是一一对应)然后用对应的Hash数组来统计个数,为了防止出现不同的sum对应相同的Hash值,还要额外开一个数组来判重。
网上很多题解是将结果+10^6后存起来,但是数组的空间浪费比较大。由于只是二重循环,最多只有100*100个不同的结果,因此只需要考虑设计一个Hashsize大于10^4的数组即可,如果发生Hash值冲突时,可以进行再散列,即不断地向右移动,看是否有别的空位可以使用。可以保证一定可以找到合适的空位来存储新的结果。但是为了减少冲突的处理,可以将Hashsize设置为所有可能结果数量的4倍或5倍。详细过程见代码。
3.代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<string> #include<sstream> #include<set> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> using namespace std; #define me(s) memset(s,0,sizeof(s)) #define pb push_back typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <int, int> P; const int M=40021;//为了减少冲突的处理,设置为所有结果数量的4倍 int f[M],g[M];//f[i]表示哈希值为i的结果的个数;g[i]表示哈希值为i对应的和sum,起到判重的作用 int t[110]; int Hash(int k) { int t=(k%M+M)%M; while(f[t]&&g[t]!=k)//当发生冲突时,不断地向右移动t,看是否有空位或者其他哈希值和k相同的位置可以用 t=(t+1)%M; return t; } int main() { int a,b,c,d,s,p,n; for(int i=1;i<101;i++) t[i]=i*i; while(~scanf("%d%d%d%d",&a,&b,&c,&d)) { if(a>0&&b>0&&c>0&&d>0||a<0&&b<0&&c<0&&d<0) { printf("0\n");continue; } me(f);me(g); n=0; for(int i=1;i<=100;i++) for(int j=1;j<=100;j++) { s=a*t[i]+b*t[j]; p=Hash(s); g[p]=s; f[p]++; } for(int i=1;i<=100;i++) for(int j=1;j<=100;j++) { s=-(c*t[i]+d*t[j]); p=Hash(s); n+=f[p]; } printf("%d\n",n*16); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u014800748/article/details/47396001