POJ3274-牛的属性-HASH-ACM
原题:POJ3274
参考:进击的阿俊
已知有n头牛,用一个K位二进制数Ak,Ak-1,...,A1表示一头牛具有的特征,Ai=1表示具有特征i。现给定按顺序排列的N头牛的k位特征值,称某个连续范围内“特征平衡”,假如在这个范围内,拥有各个特征的牛的数量都相等。求最大“特征平衡”连续范围。
分析:
用sum[i][j]( 1<=i<=n, 1<=k<=j)表示1到第i头牛中具有特征j的牛的数量。问题转化为求解满足sum[i][l] - sum[j][l] = sum[i][1] - sum[j][1](l = 1,2,..,k)的最大i - j的值。很容易想到最简单的方法,通过令d = n to 1,判断是否存在i,使得sum[i + d][j] - sum[i][j] = sum[i + d][1] - sum[i][j],时间复杂度为O(n*n*k)。由于n的最大值能达到100000,必须选择一个更加优化的方法。
1)容易验证,sum[i][l] - sum[j][l] = sum[i][1] - sum[j][1] ( l = 1,2,..,k ) 等价于sum[i][l] - sum[i][1] = sum[j][l] - sum[j][1] ( l = 1,2,...k )。因此令d[i][j] = sum[i][j] - sum[i][1] ,问题就转化为求解使得d[i][j] = d[i + size][j]的最大size。
2)为进一步简化算法,对于任意 1<= i <=n, 令sig[i] = (d[i][1] + d[i][2] + ... +d[i][k] ) % m (m为一个较大的质数)。这样,若对于i和j, sig[i] != sig[j],那么必定不会满足d[i][] = d[j][],就无需再对它进行验证;若满足sig[i] = sig[j],才需要进一步确定是否有d[i][] = d[j][]。
3)用h[k] (1 <= k <= m,m为以上取模运算的素数)记录满足sig[i] = k的i值。通过令 i = 1 to n,以此更新h[sig[i]]和largest,即可得到结果。
样例输入
7 3 7 6 7 2 1 4 2
样例输出
4
// #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> using namespace std; const int maxn = 100010; const int maxk = 31; int n, k, tmp; bool cow[maxn][maxk]; int sum[maxn][maxk]; int d[maxn][maxk]; //d 和 sig辅助计算哈希值 int s, size; const int prime = 49117; int sig[maxn]; int largest; vector <int> h[prime]; //哈希表 void search(int i, int t)//0 1 \ 2 2 \ 2 3 \ 3 4 \ { int size = h[i].size(); for (int j = 0; j < size; j++) { bool flag = 1; for (int l = 0; l < k; l++) { //printf("d[h[%d][%d]:%d][%d]:%d ==? d[%d][%d]:%d\n",i,j,h[i][j],l,d[h[i][j]][l],t,l,d[t][l]); if ( d[ h[i][j] ][l] != d[t][l] ) { flag = 0; break; } } if (flag) { if (t - h[i][j] > largest) largest = t - h[i][j]; return; } } h[i].push_back(t); //printf("i:%d push back t:%d\n",i,t); } int findLargest() { largest = 0; for (int i = 1; i <= n; i++) { search(sig[i], i); printf("%d\n",largest); } return largest; } void init() { memset(sum, 0, sizeof(sum)); memset(sig, 0, sizeof(sig)); for (int i = 0; i < prime; i++) h[i].clear(); h[0].push_back(0); for (i = 1; i <= n; i++) { for (int j = 0; j < k; j++) { sum[i][j] = sum[i - 1][j] + cow[i][j]; d[i][j] = sum[i][j] - sum[i][0]; sig[i] += d[i][j]; //printf("%d ",d[i][j]); //printf("%d ",d[i][j]); } //printf("%d\n",sig[i]); /* for (j = 0; j < k; j++) { sig[i] += d[i][j]; } */ sig[i] = abs(sig[i]) % prime; } } int main() { //while (1) { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++ ) { scanf("%d", &tmp); for (int j = 0; j < k; j++) { cow[i][j] = tmp % 2; tmp /= 2; } } init(); findLargest(); printf("%d\n", largest); //} return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)