记录一下8号做的网易笔试题,总的来说笔试难度相对easy且每个人的题目可能不同,简单记录分享下。
PS:对于题目,每个人有每个人不同的想法和解题思路,大佬们有更高效的方法欢迎讨论,但勿喷,谢谢!
TI
思路:
就一个简单的贪心,暴力拆成2的和统计个数就好了,不过多解释。
T2
思路
可dp可暴力。
dp简单的可以是两维
d
p
[
i
]
[
j
]
,
j
∈
{
0
,
1
}
dp[i][j],j\in\{0,1\}
dp[i][j],j∈{0,1},转移方程也极其简单。当然细心的可以发现,一维其实就足够了。
T3
思路
法1
这题暴力 3 n 3^n 3n也能过,大概1e7的复杂度,就是爆搜每个物品是属于第一个人还是第二个人还是抛弃,然后维护最小值。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using pii = pair<LL, LL>;
const int maxn = 16;
int n;
int a[maxn];
int ret = INT_MAX;
void dfs(int id, int l, int r, int drop) {
if (id == n + 1) {
if (l == r) {
ret = min(ret, drop);
}
return;
}
dfs(id + 1, l + a[id], r, drop);
dfs(id + 1, l, r + a[id], drop);
dfs(id + 1, l, r, drop + a[id]);
}
signed main() {
// freopen("in", "r", stdin);
// freopen("out", "w", stdout);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
ret = INT_MAX;
dfs(1, 0, 0, 0);
printf("%d\n", ret);
}
return 0;
}
法2
其实更好的方法我觉得是用二进制枚举+Hash,即先用二进制枚举所有能组成的和(二进制hash,即key=二进制,value=凑成的和),然后再枚举选择哪些商品,计算能否分开两堆且和相等,最后得到抛弃的值。应特别注意揣摩 ( S 2 − 1 ) & S (S_2-1)\&S (S2−1)&S的用法
T4
思路:
题目讲的花里胡哨,细细揣摩一下这不就是求个强连通分量,然后缩点。最后的答案就是每个强连通分量中点的个数为k,答案就是
∑
(
k
∗
(
k
−
1
)
)
/
2
\sum(k*(k-1))/2
∑(k∗(k−1))/2。
求强连通分量这里使用tarjan算法,复杂度为
O
(
n
+
m
)
O(n+m)
O(n+m)。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using pii = pair<int, int>;
const int maxn = 50050;
const int maxm = 600600;
typedef struct Edge {
int u;
int v;
int next;
Edge() { next = -1; }
}Edge;
int head[maxn], ecnt;
Edge edge[maxm];
int n, m;
int bcnt, dindex;
int dfn[maxn], low[maxn];
int stk[maxn], top;
int belong[maxn];
int in[maxn], out[maxn];
bool instk[maxn];
void init() {
memset(edge, 0, sizeof(edge));
memset(head, -1, sizeof(head));
memset(instk, 0, sizeof(instk));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(belong, 0, sizeof(belong));
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
ecnt = top = bcnt = dindex = 0;
}
void adde(int uu, int vv) {
edge[ecnt].u = uu;
edge[ecnt].v = vv;
edge[ecnt].next = head[uu];
head[uu] = ecnt++;
}
void tarjan(int u) {
int v = u;
dfn[u] = low[u] = ++dindex;
stk[++top] = u;
instk[u] = 1;
for(int i = head[u]; ~i; i=edge[i].next) {
v = edge[i].v;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instk[v]) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]) {
bcnt++;
do {
v = stk[top--];
instk[v] = 0;
belong[v] = bcnt;
} while(v != u);
}
}
int main() {
// freopen("in", "r", stdin);
// freopen("out", "w", stdout);
int uu, vv;
while(~scanf("%d %d", &n, &m)) {
init();
for (int i = 1; i <= m; i++) {
scanf("%d %d", &uu, &vv);
if (uu == vv) continue;
adde(uu, vv);
}
for(uu = 1; uu <= n; uu++) {
if(!dfn[uu]) {
tarjan(uu);
}
}
for(int i = 0; i < ecnt; i++) {
if(belong[edge[i].u] != belong[edge[i].v]) {
in[belong[edge[i].u]]++;
out[belong[edge[i].v]]++;
}
}
unordered_map<int, int> vis;
for (int i = 1; i <= n; i++) {
vis[belong[i]]++;
}
LL ret = 0;
for (const auto x : vis) {
LL cnt = x.second;
ret += (cnt - 1) * cnt / 2;
}
printf("%lld\n", ret);
}
return 0;
}