2020/8/8 网易深度学习算法笔试

第一题

题目描述:给定一个数组,求这个数组最多能被分解成长度为多少的素数数组

输入格式:n数组长度, 然后连续输入n个数作为数组的值
输出格式:最长素数数组长度

示例:
输入:
3
1 1 1
输出:
0
分析:1本身不是素数,所以他的分解为0个

输入:
3
3 5 7
输出:
6
分析:3不用分解,5={2,3},7={2,2,3},总数是6个

我自己的C++实现:

/*
我感觉只要全按照2来分解不就好了?  整数x的分解的素数个数就是 x>>=2
但是我的解法只AC了不到60%,不知道错在哪了
*/

#include <iostream>
#include <algorithm>

using namespace std;

int main(){
	int n;
	cin >> n;
	int result = 0;
	for (int i=0; i<n; i++){
		int m;
		cin >> m;
		m >>= 1;  //右移一位,相当于除以2再取整
		result += m;
	}
	
	cout << result << endl;
	return 0;
}

第二题

题目描述:排队买火车票,每个人可以给自己买(时间消耗a[i]),或者连同后面的人一起买(时间消耗b[i]),最后一个人只能给自己买,求总体的最短时间
最后的输出格式有要求08:00:40 am这种的,注意12点是am哈哈。

输入样例:
2 // 测试次数T
2 // 人数n
20 45 //a数组
40 //b数组
1
8

输出结果:
08:00:40 am
08:00:08 am

我自己的C++实现:

/*
用动态规划来求解就可以了
状态转移方程:
f[j] = min(f[j-1]+a[j], f[j-2]+b[j])

AC100%
*/

#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>

using namespace std;

const int MAXL = 2010;
int a[MAXL],b[MAXL];
int f[MAXL];

int main(){
	int T;
	cin >> T;
	
	for (int i=0; i<T; i++){
		int hour = 8, minute = 0, second = 0;
		int n;
		int result=0;
		cin >> n;
		for (int j=1; j<=n; j++) cin>>a[j];
		for (int j=1; j<=(n-1); j++) cin>>b[j];
		
		if (n==1) result = a[1];
		else{
			f[0] = 0;
			f[1] = a[1];
			for (int j=2; j<=n; j++){
				f[j] = min(f[j-1]+a[j], f[j-2]+b[j-1]);
			}
			result = f[n];
		}
		hour = (hour + result/3600)%24;
		minute = (minute + result/60)%60;
		second = (second + result % 60);
		if (hour <= 12)
			printf("%02d:%02d:%02d am\n",hour,minute,second);
		else
			printf("%02d:%02d:%02d pm\n",hour,minute,second);
	}
	return 0;
}

第三题

题目描述:给定一个数组,问至少要丢掉总共多少价值的数,才能将这个数组均等划分给两个人。

我自己的C++实现:

/* 暂时还没有思路,现在感觉有点像更加复杂一点的背包问题,但是状态转移方程并没有想出来 */

第四题

题目描述:求两个教授互相欣赏的对数。

输入:
n,m //博士人数,连接数

m 行 // 每一行代表从那个点出发到另外一个点的连接

输出:

result //互相欣赏的博士对数

输入样例:
8 9
1 3
2 1
3 2
3 4
4 5
5 6
6 7
7 8
8 5

输出结果:
9

分析:

用tarjan算法求有向图最大强连通分量
记录每个强连通分量的个数
然后对每个数求组合 C(n,2) = n(n-1)/2

我自己的C++实现:

/*
用tarjan算法求有向图最大强连通分量
记录每个强连通分量的个数
然后对每个数求组合 C(n,2) = n(n-1)/2
*/

#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>

using namespace std;

const int MAXN = 10010;

int dfn[MAXN], low[MAXN];  //dfn[i]记录被访问的时间节点, low[i]记录该节点能访问到的最早出现的节点序号
int time, group_index;
int subnum[MAXN], visited[MAXN];
stack<int> s;
vector<int> graph[MAXN];  // 邻接表存储

void Tarjan(int u){
    time ++;
    //初始化
    dfn[u] = time;
    low[u] = time;
    visited[u] = 1;
    s.push(u);

    for (int i=0; i<graph[u].size(); i++){
        int v = graph[u][i];
        if (!dfn[v]){
            Tarjan(v);
            low[u] = min(low[v], low[u]);
        }
        else if (visited[v] == 1){
            low[u] = min(low[v], low[u]);
        }
    }

    // 判断是否为根节点,若是则找到了一个新的强连通分量
    if (dfn[u] == low[u]){
        int v;
        group_index ++;
        do{
            v = s.top();
            subnum[group_index] += 1;  //记数
            visited[v] = 0;
            s.pop();
        }while(v!=u);
    }
}

int main(){
    int n, m;
    cin >> n >> m;
    for (int i=0; i<m; i++){
        int x, y;
        cin >> x >>y;
        graph[x].push_back(y);
    }

    for (int i=1; i<=n; i++){
        if (!dfn[i]){
            Tarjan(i);
        }
    }

    int result = 0;
    for (int i=1; i<=group_index; i++){
        int t = subnum[i];
        result += t*(t-1)/2;  // 对每个数求组合 C(n,2) = n(n-1)/2
    }
    cout << result << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值