7.31日阿里笔试题目分享

第一题

小强是一个农场主,农场里有n头牛,每头牛有着独一无二的体重,每一头牛的颜色可能是种颜色其中的一种,小强带了一些牛(可能为个)出来吃草。你需要回答出小强带出来的牛的组合一共有多少种可能?

注意:因为一头牛有自己的体重(没有两头牛体重相等),所以如果四头牛的体重分别是,颜色分别是和另一种方案:四头牛的体重分别是,颜色分别是,即使两个方案的颜色的种类对应的数量是相同的,但是因为颜色对应的体重不同,所以是两个不同的方案。
由于方案书可能很大,请对取模。
输入描述:
两个整数
输入:
输出:

这道题一开始还挺懵逼的,我怀疑出题人语文没学好,其实你可以把每头牛理解成一个位置,一个位置有m种可选的颜色。

简单模拟样例后可以得到

这里的i可以被理解为,小强打算带出来的牛的个数,每一头带出来的牛颜色有种可能,带头牛有种方案
用二项式定理收拾一下得到
这样的数据规模,应该用矩阵快速幂可以很快解决。

当然也有直观理解的方法,因为每头牛可以有"不带出来吃草,颜色1,颜色2,颜色3,...,颜色m"这么多不同的选择,直接得到,

#include <bits/stdc++.h>
using namespace std;

const int debug = 1;
const int size  = 5000 + 10; 
const int INF = INT_MAX>>1;
typedef long long ll;

ll quickpow_mod(ll a, ll b, ll m) {
  a %= m;
  ll res = 1;
  while (b > 0) {
    if (b & 1) res = res * a % m;
    a = a * a % m;
    b >>= 1;
  }
  return res;
}
int main(){
    // std::ios::sync_with_stdio(false);cin.tie(0);
    ll n, m;
    cin >> n >> m;
    ll mod = 1e9+7;
    cout << quickpow_mod(m+1, n, mod) << endl;
    return 0;
}

第二题

小强最近在研究某个飘洋过海的游戏。

游戏可以看成一个的方格图,从左上角到右下角的有两种地面,表示为陆地表示海洋,每次穿行只能到达上下左右四个格子之一,不能走到方格图之外。

在陆地之间穿行一格需要花费三点行动力,在海洋之间穿行一格需要花费2点行动力。
但是从陆地和从海洋到陆地穿行则需要5点行动力。

输入描述:
第一行输入两个整数,表示方格图的大小和询问次数。
随后行,每行个元素每个元素为'C'或'S',详见样例。

随后q行每行四个数字,分别代表起点的坐标和终点的坐标。

输入:
4 4 2
CCCS
SSSS
CSCS
SSCC
1 1 3 4
3 1 1 3

输出
13
14

可以看到这道题是很简单的最短路问题,因为q的数量不大,所以问一次算一次最短路就可以了,可以直接采用dijkstra算法,代码如下,

# include <climits>
# include <iostream>
# include <iomanip>
# include <vector>
# include <queue>
using namespace std;


const int INF = INT_MAX>>1;
typedef pair<int, int> coord;
typedef pair<int, coord> node;


char g[505][505];
int dist[505][505];

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1,0, 0};

int Dist(int x1, int y1, int x2, int y2){
    if (g[x1][y1] != g[x2][y2])
        return 5;
    if (g[x1][y1] == 'C')
        return 3;
    return 2;
}

int n, m, q;

bool inrange(int x, int y){
    return (1 <= x && x <= n) && (1 <= y && y <= m);
}

int main(){
    cin >> n >> m >> q;
    memset(g, 0, sizeof(g));
    for (int i = 1; i <= n; i++){
        cin >> (g[i]+1);
    }
    while (q--){
        int sx, sy, ex, ey;
        cin >> sx >> sy >> ex >> ey;
        priority_queue<node, vector<node>, greater<node> > pri_que;
        for (int i = 1; i<= n; i++){
            for (int j = 1; j <= m; j++){
                dist[i][j] = INF;
            }
        }
        dist[sx][sy] = 0;
        pri_que.push(node(dist[sx][sy], coord(sx, sy)));
        while (!pri_que.empty()){
            node T = pri_que.top(); pri_que.pop();
            int d = T.first;
            int x = T.second.first;
            int y = T.second.second;
            for (int i = 0; i < 4; i++){
                int nx = x + dx[i];
                int ny = y + dy[i];

                if (inrange(nx, ny) && dist[nx][ny] > d +  Dist(x, y, nx, ny)){
                    dist[nx][ny] = d +  Dist(x, y, nx, ny);
                    pri_que.push(node(dist[nx][ny], coord(nx, ny)));
                }
            }
        }
        cout << dist[ex][ey] <<endl;
    }
    return 0;
}

或者说,也可以考虑使用SPFA, SPFA是bellman-fold算法的一个优化版本,最坏情况效率和bellman-fold相同,优点是好些,同时一般的面试不会卡这个算法。

#include <bits/stdc++.h>
using namespace std;

const int INF = INT_MAX>>1;
typedef pair<int, int> coord;

char g[505][505];
int dist[505][505];
int inque[505][505];


int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1,0, 0};


int edge(int x1, int y1, int x2, int y2){
    if (g[x1][y1] != g[x2][y2]) 
        return 5;
    if (g[x1][y1] == 'C')
        return 3;
    return 2;
}


int n, m, q; 


bool inrange(int x, int y){
    return (1 <= x && x <= n) && (1 <= y && y <= m);     

}


int main(){
    cin >> n >> m >> q;
    memset(g, 0, sizeof(g));
    for (int i = 1; i <= n; i++){
        cin >> (g[i]+1);
    }
    while (q--){
        int sx, sy, ex, ey;
        cin >> sx >> sy >> ex >> ey;
        for (int i = 1; i<= n; i++){
            for (int j = 1; j <= m; j++){
                dist[i][j] = INF;
            }
        }
        queue<coord> que;
        dist[sx][sy] = 0;
        que.push(coord(sx, sy));
        inque[sx][sy]= 0;
        while (!que.empty()){
            coord T = que.front(); que.pop();
            int x = T.first;
            int y = T.second;
            inque[x][y] = 0;


            for (int i = 0; i < 4; i++){
                int nx = x + dx[i];
                int ny = y + dy[i];


                if (inrange(nx, ny) && dist[nx][ny] > dist[x][y] +edge(x, y, nx, ny)){
                    dist[nx][ny] = dist[x][y] + edge(x, y, nx, ny);
                    if (!inque[nx][ny]){
                        inque[nx][ny] = 1;
                        que.push(coord(nx, ny));
                    }
                }
            }
        }
        cout << dist[ex][ey] <<endl;
    }
    return 0;
}

图片说明

#笔试题目##阿里巴巴#
全部评论
第一题每头牛都有{不带,颜色1, ...,颜色m}这些选择,所以根据乘法原理答案是(m+1)^n,哈哈
4 回复 分享
发布于 2020-08-01 00:49
0AC,我跪了。还有机会面试嘛?呜呜呜
1 回复 分享
发布于 2020-07-31 21:22
https://www.nowcoder.com/discuss/464062?source_id=profile_create&channel=666 AC代码
1 回复 分享
发布于 2020-07-31 22:13
第一题怎么收拾一下的可以说说吗🤣
点赞 回复 分享
发布于 2020-07-31 21:00
请问第二题是dijkstra算法?
点赞 回复 分享
发布于 2020-07-31 21:09
我一个朋友说第二题他用dfs过得,我没见过这种神奇的算法,谁也是用dfs过得,能给我讲讲嘛?
点赞 回复 分享
发布于 2020-07-31 22:11
膜拜大佬😂想问下第一题,库自带pow底层不是快速幂吗,一定要再手写吗。还有就是没想到这个二项展开形式转换的话,用Cni *pow(m,i)累加有什么不溢出的好方法吗
点赞 回复 分享
发布于 2020-07-31 22:23
膜拜大佬,想问一下第二题的 Dijkstra 算法,在出队列的时候,不是应该选择距离 source 最近的那个节点出队列嘛?是我的理解有问题还是我没看懂代码
点赞 回复 分享
发布于 2020-08-03 11:49
第一题那里是 m  的 i 次方吧
点赞 回复 分享
发布于 2020-08-03 15:43

相关推荐

头像
11-09 17:30
门头沟学院 Java
TYUT太摆金星:我也是,好几个华为的社招找我了
点赞 评论 收藏
分享
11-05 07:29
贵州大学 Java
点赞 评论 收藏
分享
8 26 评论
分享
牛客网
牛客企业服务