hdu_1496_equations( 二分 or hash )

本文探讨了一种优化算法在解决特定数学问题上的应用。通过引入哈希表和闭散列法,文章提出了一种高效的解决方案,显著提高了计算速度。讨论了算法优化的关键步骤,包括对数值范围的合理限制、哈希函数的设计以及冲突处理策略,最终实现了一个运行时间短且准确的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于这个题目普通的暴力解法O(n^4)是必然会超时的,想到了二分但是时间复杂度还是O(n^3*log(n)) 估计还是会超时的,接着就没有写了。
对于这个问题
1.当a,b,c,d, all > 0 or all < 0 是没有解的,这个优化很重要,估计没有这个优化,对于这个题目的测试数据基本上要超时了
2.因为xi*xi ( 1 <= i <= 4) 都是大于zero的,所以只要枚举区间[1, 100] 就ok了
3.结果需要*(1<<4)表示每个循环都有负数的可能,所以每个循环*2 --> ans*16
4.这里最主要的是用到了hash以及使用闭散列法处理冲突, hash的函数设计很重要

version 1. 36ms
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define FINAL   101
#define MAXN    50021 //不同的大小会有不同的效率

int hash[MAXN], save[MAXN], arr[FINAL];

int get_idx(const int &k)
{
        int idx( k%MAXN );
        idx += (idx < 0)? MAXN : 0;
        while( hash[idx] && save[idx] != k ) {
                idx = (idx+1)%MAXN;
        }
        save[idx] = k; return idx;
}

int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int a, b, c, d, rst, idx;
        for(int i = 1; i < FINAL; i ++) {
                arr[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;
                }
                memset(hash, 0, sizeof(hash)); rst = 0;
                for(int i = 1; i < FINAL; i ++) {
                        for(int j = 1; j < FINAL; j ++) {
                                hash[ get_idx(a*arr[i]+b*arr[j]) ] ++;
                        }
                }
                for(int i = 1; i < FINAL; i ++) {
                        for(int j = 1; j < FINAL; j ++) {
                                rst += hash[ get_idx(-c*arr[i]-d*arr[j]) ];
                        }
                }
                printf("%d\n", rst*(1<<4));
        }
        return 0;
}

version 2, 300+ ms
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define FINAL   100
#define MAXN    1000001

int hash[MAXN+MAXN];

int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int a, b, c, d, val, rst;
        register int i, j;
        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;
                }
                memset(hash, 0, sizeof(hash)); rst = 0;
                for(i = 1; i <= FINAL; i ++) {
                        for(j = 1; j <= FINAL; j ++) {
                                hash[a*i*i+b*j*j+MAXN] ++;
                        }
                }
                for(i = 1; i <= FINAL; i ++) {
                        for(j = 1; j <= FINAL; j ++) {
                                rst += hash[-c*i*i-d*j*j+MAXN];
                        }
                }
                printf("%d\n", rst*(1<<4));
        }
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值