拼多多笔试,4*100,题解攒人品

A

模拟

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
int a[10][10];
int chk()
{
    if(a[1][2])
    {
        if(a[1][4]) return 7;
        return 5;
    }
    int c=0;
    for(int i=0;i<10;++i)
        c+=a[7][i];
    if(c==6) return 2;
    if(c==2) return 4;
    c=0;
    for(int i=0;i<10;++i)
        c+=a[i][2];
    if(!c) return 1;
    if(c==4) return 8;
    if(c==2)
    {
        if(a[3][2]) return 9;
        return 3;
    }
    if(a[4][4]) return 6;
    return 0;
}
int main()
{
    int QAQ;cin>>QAQ;
    while(QAQ--)
    {
        int n;cin>>n;
        int k=n/10;
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                cin>>a[i/k][j/k];
        cout<<chk()<<endl;
    }
}

B

迷宫

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
const int N=25;
char mp[N][N];
int d[N][N];
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int n,m;
bool in(int x,int y){return x<n&&y<m&&x>=0&&y>=0;}
int main()
{
    vector<pii>ans;
    cin>>n>>m;
    typedef array<int,3> ar3;
    ar3 p;
    for(int i=0;i<n;++i)
    {
        cin>>mp[i];
        for(int j=0;j<m;++j)
            if(mp[i][j]=='T')
                p={i,j,0};
    }
    queue<ar3>q;
    int md=1<<30;
    q.push(p);
    memset(d,-1,sizeof(d));
    d[p[0]][p[1]]=0;
    while(!q.empty())
    {
        auto now=q.front();q.pop();
        int x=now[0],y=now[1],dis=now[2];
        if(mp[x][y]=='X')
        {
            if(dis<md)
                md=dis,ans=vector<pii>{{x,y}};
            else if(dis==md)
                ans.push_back({x,y});
        }
        for(int i=0;i<4;++i)
        {
            int nx=x+dx[i],ny=y+dy[i];
            if(in(nx,ny)&&mp[nx][ny]!='1')
            {
                if(d[nx][ny]==-1)
                {
                    d[nx][ny]=dis+1;
                    q.push({nx,ny,dis+1});
                }
            }
        }
    }
    if(ans.empty())
        cout<<0<<endl;
    else
    {
        cout<<md<<endl;
        sort(all(ans));
        for(auto&pp:ans)
            cout<<pp.fi<<' '<<pp.se<<' ';
    }
}

C

n个点的树,点带权,有边相连的两点不能同时被选,要求选k个,求最大权值和,无法取到k个输出-1.

/*
dp[n][k][2]:
    dp[i][j][t]表示以i节点为根的子树下,选择j个点,其中包括i节点(t=1)/不包括i节点(t=0)能取到的最大权值和,以节点1为根做树形背包,max(dp[1][k][0],dp[1][k][1])即为答案。转移参考背包。
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
const int N=1<<14;
const int K=1<<7;
vector<int>G[N];
int a[N],dp[N][K][2],sz[N];
int n,k;
void dfs(int u,int p)
{
    sz[u]=1;
    vector<int>son;
    son.push_back(0);
    for(int&v:G[u])
    {
        if(v==p) continue;
        son.pb(v);
    }
    int z=son.size()-1;
    vector<vector<int>>f(z+1,vector<int>(k+1,-1));    //f[i][j]表示前i个儿子取j个最大权值和,其中只对不选儿子的情况进行背包,因为要用来转移到dp[u][i][1]。
    vector<vector<int>>g(z+1,vector<int>(k+1,-1));    //g[i][j]表示前i个儿子取j个最大权值和,不限制是否选择儿子。
    f[0][0]=g[0][0]=0;
    for(int i=1;i<=z;++i)
    {
        int v=son[i];
        dfs(v,u);
        for(int j=0;j<=sz[v];++j)
            if(~dp[v][j][0])
                for(int o=k;o>=j;--o)
                    if(~f[i-1][o-j])
                        f[i][o]=max(f[i][o],f[i-1][o-j]+dp[v][j][0]);
        for(int j=0;j<=sz[v];++j)
            for(int o=0;o<2;++o)
                if(~dp[v][j][o])
                    for(int l=k;l>=j;--l)
                        if(~g[i-1][l-j])
                            g[i][l]=max(g[i][l],g[i-1][l-j]+dp[v][j][o]);
        sz[u]+=sz[v];
    }
    for(int i=0;i<=k;++i)
        dp[u][i][0]=g[z][i];
    for(int i=1;i<=k;++i)
        if(~f[z][i-1])
        {
            dp[u][i-1][0]=max(f[z][i-1],dp[u][i-1][0]);
            dp[u][i][1]=f[z][i-1]+a[u];
        }
}
int main()
{
    int QAQ;cin>>QAQ;while(QAQ--)
    {
        memset(dp,-1,sizeof(dp));
        cin>>n>>k;
        for(int i=1;i<=n;++i) G[i].clear();
        for(int i=1;i<=n;++i) cin>>a[i];
        for(int i=1,u,v;i<n;++i)
        {
            cin>>u>>v;
            G[u].pb(v);
            G[v].pb(u);
        }
        dfs(1,0);
        cout<<max(dp[1][k][0],dp[1][k][1])<<endl;
    }
}

D

n行m列的道路,,有两种规格的瓷砖分别是,问多少种方案铺满道路,答案对取模。

本质上是求有多少种放的方案,因为只要放完,剩下的全放就行。注意到很小,可以对状态压缩,用一个数字表示当前状态,如果的二进制表示位为1,那么该状态的第个位置有瓷砖。

例如,那么当前行全部铺满了,要注意有些状态不合法,比如,原因是现在只铺的瓷砖,那么的个数必须为偶数,且要能划分为若干个连续的,下面用表示状态是否合法,可以简单预处理出来。

然后用来解决这个问题。显然,如果,那只有一种方案,因为放不下,否则我们用来表示在第行,且第行状态为的方案数。从第二行开始。转移方程如下(为所有合法状态集合)。
每行状态个数最多为,有行,转移复杂度为,总复杂度为显然爆炸。考虑优化。

观察转移方程,可以发现是个递推,我们可以预处理出一个矩阵,其中
那么,把看作一个的矩阵,显然有
最后所有元素求和即为答案。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
const int M=5;
const int K=1<<M;
const int mod=1000000007;
bool o[K];            //legal[K]
bool ok(int x)        //检查状态x是否合法
{
    int c=__builtin_popcount(x);
    if(c&1) return 0;
    for(int i=0;i<M;++i)
    {
        if(!((x>>i)&1)) continue;
        if(i==M-1) return 0;
        if(!((x>>(i+1))&1)) return 0;
        ++i;
    }
    return 1;
}
bool ok(int x,int y)    //判断y是否能从x转移过来。
{
    if(!o[x]||!o[y]) return 0;
    return (x&y)==0;
}
string s(int x){string ret;if(!x) return "0";while(x)ret+='0'|(x&1),x>>=1;return ret;}                    //调试输出用。
void add(int &x,int y){x+=y;if(x>=mod) x-=mod;}
int mul(const int&x,const int&y){return 1LL*x*y%mod;}
struct Mat
{
    int n;
    int a[K][K];
    Mat(){for(int i=0;i<K;++i)a[i][i]=1;}
    Mat(int z)
    {
        memset(a,0,sizeof(a));
        if(z==0) return;
        n=z;
        for(int i=0;i<n;++i)    //初始化为单位矩阵
            a[i][i]=1;
    }
    Mat operator*(Mat w)    //矩阵乘法
    {
        Mat ret(0);
        ret.n=n;
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                for(int k=0;k<n;++k)
                    add(ret.a[i][j],mul(a[i][k],w.a[k][j]));
        return ret;
    }
    void output()
    {
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                cout<<a[i][j]<<" \n"[j==n-1];
        cout<<endl;
    }
};
Mat qp(Mat A,int b,int n)    //矩阵快速幂。
{
    Mat ret(n);
    for(;b;b>>=1,A=A*A)
        if(b&1) ret=ret*A;
    return ret;
}
int main()
{
    int n,m;cin>>n>>m;
    if(min(n,m)==1) return cout<<1<<endl,0;
    for(int i=0;i<K;++i)
        o[i]=ok(i);
    int k=1<<m;
    Mat A(k);
    for(int i=0;i<k;++i)
        for(int j=0;j<k;++j)
            A.a[i][j]=ok(i,j);        //矩阵A初始化
    A=qp(A,n-1,k);                    //A=A^(n-1)
    int ans=0;
    for(int i=0;i<k;++i)
        add(ans,A.a[i][0]);            //A第一行/第一列的和即为答案
    cout<<ans<<endl;
}
#拼多多##笔试题目##题解#
全部评论
这能讲讲思路就更好了。
2 回复 分享
发布于 2020-09-27 12:33
tql 膜拜
1 回复 分享
发布于 2020-09-26 21:50
我知道一定有人ak。但还是忍不住发出一声:膜!
1 回复 分享
发布于 2020-09-26 22:05
牛逼,我就是没优化,只能过百分之五,老哥你是真的强
点赞 回复 分享
发布于 2020-09-26 21:38
大佬好强
点赞 回复 分享
发布于 2020-09-26 21:48
太强了tql 膜拜
点赞 回复 分享
发布于 2020-09-26 21:57
tql
点赞 回复 分享
发布于 2020-09-26 22:35
太厉害啦,膜拜
点赞 回复 分享
发布于 2020-09-26 23:17
点赞 回复 分享
发布于 2020-09-26 23:37
tql
点赞 回复 分享
发布于 2020-09-26 23:38
点赞 回复 分享
发布于 2020-09-26 23:52
ak也没有面试的,我上一场就ak了。
点赞 回复 分享
发布于 2020-09-26 23:54
大佬能帮我看一下第一题c++代码吗,我示例能通过,但是case通过率为0哭了,我没有在输入的时候除10 ,而是选择在检测的时候x10
点赞 回复 分享
发布于 2020-09-27 04:39
tql
点赞 回复 分享
发布于 2020-09-27 10:49
tql
点赞 回复 分享
发布于 2020-09-27 10:54
太厉害了
点赞 回复 分享
发布于 2020-09-27 11:21
***是神仙
点赞 回复 分享
发布于 2020-09-27 12:50
真的强
点赞 回复 分享
发布于 2020-09-27 15:31
TQL
点赞 回复 分享
发布于 2020-09-27 15:47
楼主是acmer嘛
点赞 回复 分享
发布于 2020-09-27 18:27

相关推荐

努力学习的小绵羊:我反倒觉得这种挺好的,给不到我想要的就别浪费大家时间了
点赞 评论 收藏
分享
评论
28
37
分享
牛客网
牛客企业服务