hdu 1800 Flying to the Mars

hdu 1800 Flying to the Mars

  • 题意:找出题给的最少的递增序列(严格递增)的个数,其中序列中每个数字不多于30位;序列长度不长于3000;
    input:
    4 (n)
    10
    20
    30
    04
    output
    1
  • 思路:将节目转化为相同数的最多个数即可~~
    这时就随便怎么搞了。我是直接用了map(开始不会hash啊…)来找mx;
    但是和字符串hash相比,时间性能不好。
    之后看了ACdreamers,学习了ELFhash之后发现挺好用的~~下面将讲解一下我对ELFhash的理解。

map::code

702ms 1808k
#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0;i < (n);i++)
map<string,int> mp;
int main()
{
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cerr<<"";
    int n,i;
    while(cin>>n){
        mp.clear();
        string str;
        rep(i,n){
            cin>>str;
            int j = 0;
            for(;j < str.size();j++)if(str[j] != '0') break;
            mp[str.substr(j)]++;
        }
        int ans = 0;
        for(auto m : mp){
            ans = max(ans , m.second);
        }
        cout<<ans<<endl;
    }
}

ELFhash( );
hash要对字符串里面的每一个字符进行运算,之后得到一个”相对”不同的值(因为有冲突);原本字符是有八个字节的,但是里面对高位的四个字节与前一个字符的低的四个字节相加了,低的四个字节填补了h左移空出来的四个字节(不知理解得是否有误,若有误,请指正~)并且里面的位是从0开始的,即当h<<4时开始的0位,现在就是第4位了。里面的hash运算还有就是在h要满的时候(即h的高四位28~31不为0时),下一次再加进字符时,就会直接移走了,但是算法要将这高四位和4~8位的数再做一次XOR运算,应该是使得得到的hash更随机~~(里面0xF0000000L就表示28~31位全是1,其余位为0)。

unsigned int ELFhash(char *str)
{
    unsigned int h = 0;
    unsigned int x;
    while(*str){
        h = (h << 4) + *str++;
        x = h & 0xF0000000L;
        if(x){
            h ^= x>>24;  // 4 ~ 8位与高四位做XOR运算;
            h &= ~x;   // h清空28~31位(运算完了)
        }
    }
    return h & 0x7FFFFFFF;//返回正数;
}

hash::code @ACdreamers

499ms 
#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0;i < (n);i++)
#define MS0(a) memset(a,0,sizeof(a))
const int MOD = 100007;
int Hash[MOD],cnt[MOD];
unsigned int ELFhash(char *str)
{
    unsigned int h = 0;
    unsigned int x;
    while(*str){
        h = (h << 4) + *str++;
        x = h & 0xF0000000L;
        if(x){
            h ^= x>>24;
            h &= ~x;
        }
    }
    return h & 0x7FFFFFFF;
}
int Hashhit(char *str)
{
    while(*str == '0') str++;
    int k = ELFhash(str);
    int t = k % MOD;
    while(Hash[t] && Hash[t] != k) //解决冲突;
        t = (t + 10)%MOD;
    if(Hash[t] == 0)
        Hash[t] = k;
    return ++cnt[t];
}
int main()
{
    int n;char str[33];
    while(scanf("%d",&n) == 1){
        MS0(Hash);MS0(cnt);
        int ans = 0;
        rep(i,n){
            scanf("%s",str);
            ans = max(ans,Hashhit(str));
        }
        printf("%d\n",ans);
    }
}

“`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值