hdu 1496 巧妙的hash

来源:互联网 发布:sql语法名称 编辑:程序博客网 时间:2024/05/06 09:16

这道题可以用暴力来解决,也就是2个两层循环。。。但是如果用一个四层循环则必定TLE。。

这道题hash思路:

题目是要求 a*x1*x1+b*x2*x2+c*x3*x3+d*x4*x4=0 有多少种解;

那么等式左边是a*x1*x1+b*x2*x2

等式右边是-(c*x3*x3+d*x4*x4); 只要把等式左边hash一下,然后等式右边去遍历一遍即可

附上代码:

#include <iostream>#include <cstdio>#include <cmath>#include <stdio.h>#include <string.h>#define N 51000     //因为等式左边最多有10000种可能 所以开个50000的数组足够了using namespace std;int f[N],g[N];int hash(int x){  int t=x%N;  if(t<0)t+=N;  while(g[t]!=0&&f[t]!=x)     t=(t+1)%N;  return t;}int main(){ int a,b,c,d,s,l; int p[102]; for(int i=1;i<=100;i++)    p[i]=i*i; while(cin>>a>>b>>c>>d) {   if(a>0&&b>0&&c>0&&d>0)   {cout<<0<<endl;                        continue;   }    if(a<0&&b<0&&c<0&&d<0)   {    cout<<0<<endl;    continue;   }   memset(f,0,sizeof(f));   memset(g,0,sizeof(g));   for(int i=1;i<=100;i++)    for(int j=1;j<=100;j++)    {       s=a*p[i]+b*p[j];       l=hash(s);        f[l]=s;            //f表示l位置上装的真值       g[l]++;            //表示l位置上同一个真值的个数    }   int cnt=0;   for(int i=1;i<=100;i++)    for(int j=1;j<=100;j++)    {      s=-(c*p[i]+d*p[j]);      l=hash(s);      cnt+=g[l];     }  cout<<cnt*16<<endl;   //之所以乘以16是因为平方,每个有两种可能,可正可负 } return 0;}


0 0