搜狗2016研发工程师编程题
来源:互联网 发布:软件结项文档 编辑:程序博客网 时间:2024/05/19 21:41
题目链接:点这里.
这套题目还是很有质量的,都是暴力过不了的题,但是觉得牛客网数据还是有点水,很多人都暴力过了……,第一题要二分,而且选对数据结构对代码的复杂度有很大的减低;第二题简单的动态规划,处理好非负数就好了.
第一题:火眼金睛
题目:
现在我们需要查出一些作弊的问答社区中的ID,作弊有两种:1.A回答了B的问题,同时B回答了A的问题。那么A和B都是作弊。2.作弊ID用户A和作弊ID用户B同时回答了C的问题,那么C也是作弊。已知每个用户的ID是一串数字,一个问题可能有多个人回答。
解析:
首先要考虑ID可能是离散的,所以要双向
map ,不过后台数据貌似是连续的;其次先求出第一种方式作弊的ID,这里要用到二分,选用的是STL中的
set ,自动二分查找而且不用考虑重复的问题,然后用选出的ID不断选出第二种方式作弊的ID;最后再把连续的ID映射回原ID,这里也用
set ,自动排序.
代码:
#include <bits/stdc++.h>using namespace std;int main(){ int n; while (~scanf("%d", &n)) { map<int, int> mp, toSrc; int ids = 0; vector<set<int> > arr(n + 1); for (int i = 0; i < n; i++) { int id_top, numOfAnswer; scanf("%d%d", &id_top, &numOfAnswer); if (mp.find(id_top) == mp.cend()) mp[id_top] = ids++, toSrc[mp[id_top]] = id_top; int question = mp[id_top]; for (int j = 0; j < numOfAnswer; j++) { int id; scanf("%d", &id); if (mp.find(id) == mp.cend()) mp[id] = ids++, toSrc[mp[id]] = id; if (mp[id] == question) continue; arr[question].insert(mp[id]); } } set<int> ans; for (int i = 0; i < n; i++) { for (auto it = arr[i].begin(); it != arr[i].end(); ++it) { if (arr[*it].find(i) != arr[*it].cend()) { ans.insert(i); ans.insert(*it); } } } while (true) { bool isOk = true; for (int i = 0; i < n; i++) { if (ans.find(i) != ans.cend()) continue; for (auto it1 = arr[i].begin(); it1 != arr[i].end(); ++it1) { auto it2 = it1; for (++it2; it2 != arr[i].end(); ++it2) { if (ans.find(*it1) != ans.cend() && ans.find(*it2) != ans.cend()) { isOk = false; ans.insert(i); goto F; } } } F:; } if (isOk) break; } set<int> theAns; for (auto it = ans.begin(); it != ans.end(); ++it) theAns.insert(toSrc[*it]); printf("%d\n", theAns.size()); bool isFirst = true; for (auto it = theAns.begin(); it != theAns.end(); ++it) { if (!isFirst) putchar(' '); isFirst = false; printf("%d", *it); } if (!isFirst) puts(""); } return 0;}
第二题:矩阵元素相乘
题目:
A[n,m] 是一个n 行m 列的矩阵,a[i,j] 表示A 的第i 行j 列的元素,定义x[i,j] 为A 的第i 行和第j 列除了a[i,j] 之外所有元素(共n+m−2 个)的乘积,即x[i,j]=a[i,1]∗a[i,2]∗...∗a[i,j−1]∗...∗a[i,m]∗a[1,j]∗a[2,j]...∗a[i−1,j]∗a[i+1,j]...∗a[n,j] ,现输入非负整形的矩阵A[n,m] ,求MAX(x[i,j]) ,即所有的x[i,j] 中的最大值。
解析:
暴力肯定超时,我们预处理出两个方向的总体乘积,但是如果矩阵中有0,那么预处理出来的乘积就不对,因此,我们再遇到0的时候乘1,然后在预处理出每行每列有多少个0.
维护最大值时,如果发现某一行或某一列有两个以上的0,那么这个
[i,j] 就不用计算了,如果当前元素是0,且这一行和这一列只有一个0,那么就可以用这行的积乘这列的积再除以当前元素的平方来维护最大值.由于事先不知道数据范围的大小,我又不想动态分配内存了,因此选用了STL中的
vector .
代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;int main(){ int n, m; while (cin >> n >> m) { vector<vector<int> > matrix(n + 1, vector<int>(m + 1)); vector<vector<vector<LL> > > dp(2, vector<vector<LL> >(n + 1, vector<LL>(m + 1, 1))); vector<int> x(n + 1, 0), y(m + 1, 0); for (int i = 1; i <= n; i++) { LL sum = 1; for (int j = 1; j <= m; j++) { int xx; cin >> xx; matrix[i][j] = xx; if (!xx) { xx = 1; x[i]++; y[j]++; } dp[0][i][j] = dp[0][i][j] * (sum *= xx); } for (int j = 1; j <= m; j++) { if (!matrix[i][j]) dp[1][i][j] = dp[1][i - 1][j]; else dp[1][i][j] = dp[1][i - 1][j] * matrix[i][j]; } } LL ans = 0; for (int i = 1; i <= n; i++) { if (x[i] > 1) continue; for (int j = 1; j <= m; j++) { if (!matrix[i][j] && y[j] > 1) continue; LL tag = matrix[i][j] == 0 ? 1 : matrix[i][j]; ans = max(ans, dp[0][i][m] * dp[1][n][j] / (tag * tag)); } } cout << ans << endl; } return 0;}
- 搜狗2016研发工程师编程题
- 搜狗2016研发工程师编程题
- 矩阵元素相乘----搜狗2016研发工程师编程题
- 苏宁2016研发工程师编程题
- 百度2016研发工程师在线编程题
- 华为2016研发工程师编程题
- 华为2016研发工程师编程题
- 腾讯2016研发工程师编程题
- 网易2016研发工程师编程题
- 网易2016研发工程师编程题
- 网易2016研发工程师编程题 搜索
- 网易2016研发工程师编程题①
- 网易2016研发工程师编程题②
- 腾讯2016研发工程师编程题
- 网易2016研发工程师编程题
- 腾讯2016研发工程师编程题
- 网易2016 实习研发工程师编程题
- 网易2016实习研发工程师编程题
- 【第五周项目4】数制转换
- PPT制作流程 --- 早看早超生
- 黑客工具软件大全100套
- 合并有序单链表并排序(遍历一次)
- Studio像Eclipse一样设置switch/case那样的代码块
- 搜狗2016研发工程师编程题
- iOS-Xcode 上传App Store遇到 Unexpected CFBundleExecutable Key问题
- sql文件反向生成物理概念模型
- 黑客工具软件大全100套
- leetcode
- 网络安全之相关攻击方式总结
- Kotlin从入门到放弃之基础篇(五)——修饰词、扩展、数据类
- 机器学习_协方差
- Servlet Session(会话)