HDU 1496 Equations(hash or 二分)
2013-08-10 09:14
483 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1496
这个题目要注意剪枝,也就是如果四个系数同号,那么结果就一定是0,如过没有这个剪枝,那么很可能超时
方法一:
hash,这个方法还是比较容易想的,因为a b c d的范围和xi的范围都不大,直接hash就肯定能搞定了,这个方法比较容易实现
方法二:
二分,题目中方程式可以转换成 a b在一边,c d在一边,完成之后先处理c d,然后处理a b的时候直接在预先处理的c d中二分
查找,这个程序写袭来有很多细节,和值得优化的地方,因为数据结果 c d部分会有很多是相同的,所以在二分之前要压缩一下
但是在压缩的时候要记住没个相同的数字出现的次数,如果不这样会漏掉大量解,而且用二分也是错的,二分每次查找的是存在
还是不存在,或者说存在的位置,往往是找到一个就放手了,如果我们压缩一下就能保证每个只出现一次,那么才能保证结果正
确,而且也能减少二分次数,大概减少一次!
hash代码:
/*1496*/
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define maxn 2000000
int a,b,c,d;
int pos;
int rec[maxn*2];
int init()
{
memset(rec,0,sizeof(rec));
pos=0;
int i,j,k;
for(i=-100;i<0;i++)
{
k=-c*i*i+maxn;
for(j=-100;j<0;j++)
rec[k-d*j*j]++;
for(j=1;j<=100;j++)
rec[k-d*j*j]++;
}
for(i=1;i<=100;i++)
{
k=-c*i*i+maxn;
for(j=-100;j<0;j++)
rec[k-d*j*j]++;
for(j=1;j<=100;j++)
rec[k-d*j*j]++;
}
return 0;
}
int solve()
{
int ans=0;
int i,j,k;
for(i=-100;i<0;i++)
{
k=a*i*i+maxn;
for(j=-100;j<0;j++)
ans+=rec[k+b*j*j];
for(j=1;j<=100;j++)
ans+=rec[k+b*j*j];
}
for(i=1;i<=100;i++)
{
k=a*i*i+maxn;
for(j=-100;j<0;j++)
ans+=rec[k+b*j*j];
for(j=1;j<=100;j++)
ans+=rec[k+b*j*j];
}
return ans;
}
int main()
{
int i,j,k,num;
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;
}
init();
k=1;
// for(i=1;i<pos;i++)
printf("%d\n",solve());
}
return 0;
}
二分代码:
/*1496*/
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define maxn 41000
int a,b,c,d;
int pos;
struct point
{
int value;
int num;
}rec[maxn];
int init()
{
pos=0;
int i,j;
for(i=-100;i<0;i++)
{
for(j=-100;j<0;j++)
rec[pos++].value=-c*i*i-d*j*j;
for(j=1;j<=100;j++)
rec[pos++].value=-c*i*i-d*j*j;
}
for(i=1;i<=100;i++)
{
for(j=-100;j<0;j++)
rec[pos++].value=-c*i*i-d*j*j;
for(j=1;j<=100;j++)
rec[pos++].value=-c*i*i-d*j*j;
}
return 0;
}
int find_ans(int num)
{
int l=0,r=pos-1,mid;
while(l<=r)
{
mid=(l+r)>>1;//printf("OK:%d %d %d\n",mid,rec[mid],num);
if(rec[mid].value==num)
return rec[mid].num;
if(rec[mid].value>num)
r=mid-1;
else
l=mid+1;
}
return 0;
}
int solve()
{
int ans=0;
int i,j;
for(i=-100;i<0;i++)
{
for(j=-100;j<0;j++)
ans+=find_ans(a*i*i+b*j*j);
for(j=1;j<=100;j++)
ans+=find_ans(a*i*i+b*j*j);
}
for(i=1;i<=100;i++)
{
for(j=-100;j<0;j++)
ans+=find_ans(a*i*i+b*j*j);
for(j=1;j<=100;j++)
ans+=find_ans(a*i*i+b*j*j);
}
return ans;
}
bool cmp(const point &a,const point &b)
{
return a.value < b.value;
}
int main()
{
int i,j,k,num;
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;
}
init();
sort(rec,rec+pos,cmp);
k=1;
rec[0].num=1;
for(i=1;i<pos;i++)
if(rec[i].value!=rec[i-1].value)
{
rec[k]=rec[i];
rec[k].num=1;
k++;
}
else
{
rec[k-1].num++;
}
pos=k;
printf("%d\n",solve());
}
return 0;
}
这个题目要注意剪枝,也就是如果四个系数同号,那么结果就一定是0,如过没有这个剪枝,那么很可能超时
方法一:
hash,这个方法还是比较容易想的,因为a b c d的范围和xi的范围都不大,直接hash就肯定能搞定了,这个方法比较容易实现
方法二:
二分,题目中方程式可以转换成 a b在一边,c d在一边,完成之后先处理c d,然后处理a b的时候直接在预先处理的c d中二分
查找,这个程序写袭来有很多细节,和值得优化的地方,因为数据结果 c d部分会有很多是相同的,所以在二分之前要压缩一下
但是在压缩的时候要记住没个相同的数字出现的次数,如果不这样会漏掉大量解,而且用二分也是错的,二分每次查找的是存在
还是不存在,或者说存在的位置,往往是找到一个就放手了,如果我们压缩一下就能保证每个只出现一次,那么才能保证结果正
确,而且也能减少二分次数,大概减少一次!
hash代码:
/*1496*/
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define maxn 2000000
int a,b,c,d;
int pos;
int rec[maxn*2];
int init()
{
memset(rec,0,sizeof(rec));
pos=0;
int i,j,k;
for(i=-100;i<0;i++)
{
k=-c*i*i+maxn;
for(j=-100;j<0;j++)
rec[k-d*j*j]++;
for(j=1;j<=100;j++)
rec[k-d*j*j]++;
}
for(i=1;i<=100;i++)
{
k=-c*i*i+maxn;
for(j=-100;j<0;j++)
rec[k-d*j*j]++;
for(j=1;j<=100;j++)
rec[k-d*j*j]++;
}
return 0;
}
int solve()
{
int ans=0;
int i,j,k;
for(i=-100;i<0;i++)
{
k=a*i*i+maxn;
for(j=-100;j<0;j++)
ans+=rec[k+b*j*j];
for(j=1;j<=100;j++)
ans+=rec[k+b*j*j];
}
for(i=1;i<=100;i++)
{
k=a*i*i+maxn;
for(j=-100;j<0;j++)
ans+=rec[k+b*j*j];
for(j=1;j<=100;j++)
ans+=rec[k+b*j*j];
}
return ans;
}
int main()
{
int i,j,k,num;
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;
}
init();
k=1;
// for(i=1;i<pos;i++)
printf("%d\n",solve());
}
return 0;
}
二分代码:
/*1496*/
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define maxn 41000
int a,b,c,d;
int pos;
struct point
{
int value;
int num;
}rec[maxn];
int init()
{
pos=0;
int i,j;
for(i=-100;i<0;i++)
{
for(j=-100;j<0;j++)
rec[pos++].value=-c*i*i-d*j*j;
for(j=1;j<=100;j++)
rec[pos++].value=-c*i*i-d*j*j;
}
for(i=1;i<=100;i++)
{
for(j=-100;j<0;j++)
rec[pos++].value=-c*i*i-d*j*j;
for(j=1;j<=100;j++)
rec[pos++].value=-c*i*i-d*j*j;
}
return 0;
}
int find_ans(int num)
{
int l=0,r=pos-1,mid;
while(l<=r)
{
mid=(l+r)>>1;//printf("OK:%d %d %d\n",mid,rec[mid],num);
if(rec[mid].value==num)
return rec[mid].num;
if(rec[mid].value>num)
r=mid-1;
else
l=mid+1;
}
return 0;
}
int solve()
{
int ans=0;
int i,j;
for(i=-100;i<0;i++)
{
for(j=-100;j<0;j++)
ans+=find_ans(a*i*i+b*j*j);
for(j=1;j<=100;j++)
ans+=find_ans(a*i*i+b*j*j);
}
for(i=1;i<=100;i++)
{
for(j=-100;j<0;j++)
ans+=find_ans(a*i*i+b*j*j);
for(j=1;j<=100;j++)
ans+=find_ans(a*i*i+b*j*j);
}
return ans;
}
bool cmp(const point &a,const point &b)
{
return a.value < b.value;
}
int main()
{
int i,j,k,num;
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;
}
init();
sort(rec,rec+pos,cmp);
k=1;
rec[0].num=1;
for(i=1;i<pos;i++)
if(rec[i].value!=rec[i-1].value)
{
rec[k]=rec[i];
rec[k].num=1;
k++;
}
else
{
rec[k-1].num++;
}
pos=k;
printf("%d\n",solve());
}
return 0;
}
相关文章推荐
- hdu_1496_equations( 二分 or hash )
- hdu 题目1496 Equations , POJ 题目1840 Eqs (整数Hash)
- HDU 1496 Equations(大整数的hash)
- hdu 1496 Equations(hash)@
- HDU 1496 Equations[HASH]
- hdu 1496 Equations (双重循环+hash查找)
- Equations(hdu 1496 二分查找+各种剪枝)
- HDU 1496 Equations 【整数Hash】
- hdu 1496 Equations ——hash
- HDU 1496 Equations hash HDU上排名第一!
- HDU-1496 Equations [hash]
- HDU 1496 Equations hash HDU上排名第一!
- HDU 1496 Equations (hash)
- HDU 1496 Equations(哈希打表+二分暴力)
- Equations(HDU_1496) hash
- hdu 1496 Equations (hash)
- (hash)hdu 1496 Equations
- HDU-1496-Equations && POJ-1840-Eqs (hash)
- hdu 1496 Equations (暴力+hash)
- Hdu 1496 Equations [hash]及memset效率分析