zoukankan      html  css  js  c++  java
  • BZOJ2081 [POI2010]Beads

    题目蓝链

    Solution

    首先(mathcal{O}(n))预处理出任意一个前缀的HASH值,然后就可以(mathcal{O}(1))求出任意区间的HASH值

    然后就直接枚举(k),统计一下出现了多少种不同的区间段就可以了,用(map)或HASH表均可以实现

    时间复杂度(mathcal{O}(k cdot ln(k)))

    Code

    #include <bits/stdc++.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/hash_policy.hpp>
    
    using namespace std;
    
    #define squ(x) ((LL)(x) * (x))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long LL;
    typedef pair<int, int> pii;
    
    inline int read() {
    	int sum = 0, fg = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
    	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    	return fg * sum;
    }
    
    const int base = 19260817;
    const int mod = 998244353;
    const int maxn = 2e5 + 10;
    
    __gnu_pbds::gp_hash_table<int, bool> mp;
    
    int add(int x, int y) {
    	x += y;
    	if (x >= mod) x -= mod;
    	if (x < 0) x += mod;
    	return x;
    }
    int mul(int x, int y) { return (LL)x * y % mod; }
    
    int n, a[maxn], b[maxn], Pow[maxn], q[maxn], top;
    
    int main() {
    #ifdef xunzhen
    	freopen("hash.in", "r", stdin);
    	freopen("hash.out", "w", stdout);
    #endif
    
    	n = read(); Pow[0] = 1;
    	for (int i = 1; i <= n; i++) Pow[i] = mul(Pow[i - 1], base);
    	for (int i = 1; i <= n; i++) a[i] = add(mul(a[i - 1], base), b[i] = read());
    	for (int i = n; i >= 1; i--) b[i] = add(mul(b[i + 1], base), b[i]);
    
    	int ans = 0;
    	for (int k = 1; k <= n; k++) {
    		int cnt = 0;
    		mp.clear();
    		for (int i = 1; i <= n; i += k) {
    			int l = i, r = i + k - 1;
    			if (r > n) continue;
    			int hash1 = add(a[r], -mul(a[l - 1], Pow[k]));
    			int hash2 = add(b[l], -mul(b[r + 1], Pow[k]));
    			if (mp.find(hash1) == mp.end()) cnt++, mp[hash1] = 1, mp[hash2] = 1;
    		}
    		if (cnt == ans) q[++top] = k;
    		if (cnt > ans) {
    			ans = cnt;
    			q[top = 1] = k;
    		}
    	}
    
    	printf("%d %d
    ", ans, top);
    	for (int i = 1; i <= top; i++) printf("%d%c", q[i], i < top ? ' ' : '
    ');
    
    	return 0;
    }
    

    Summary

    这应该算是我做的第一道比较正式的HASH题了,第一次用了求区间HASH值的这个技巧

    done(2018.8.31)
    upt(2018.9.26): 之前写的题,一直没发

  • 相关阅读:
    java DES转C#DES加密解密
    PIE SDK影像格式转换
    PIE SDK位深转换
    PIE SDK存储格式转换
    PIE SDK栅格生成等值线、面
    PIE SDK反距离权重插值算法
    PIE SDK克里金插值法
    PIE SDK热力图
    PIE SDK Alpha通道数据渲染
    PIE SDK 多数据源的复合数据集加载
  • 原文地址:https://www.cnblogs.com/xunzhen/p/9710492.html
Copyright © 2011-2022 走看看