当前位置: 首页 > 面试经验 >

米哈游后端笔试题解

优质
小牛编辑
103浏览
2023-03-28

米哈游后端笔试题解

第一题是算联通块,两次dfs即可,太简单,不细说了

第二题 算添加删除mhy的,也挺简单的,不说了

第三题:

给你一个n的数组a,数组中元素不重复,1<= 元素大小 <=1000000

n为 [1,100000]

求从数组中挑选多于一个元素的子集(至少两个元素),使得子集中元素两两为倍数关系

的方案数 (mod 1000000007)

解法:

把数组a递增排序

预处理这个数组间 的倍数关系 (nlog1000000)

再nlog 去dp一下

dp含义 :sum[x]表示以x元素作为结尾的方案数

转移方程:(条件:a中存在u,且a[i]是u倍数,u!=a[i])

sum[a[i]] += sum[u]+1;

代表u结尾的所有合法子集均添加一个a[i] 的方案数: sum[u]

以及单一个u的集合加 a[i] 也能构成新的合法集合的方案数: 1

故u对a[i]的贡献为 sum[u]+1

记得mod一下 :sum[a[i]]=(sum[a[i]]+sum[u]+1)%mod;

最后,c++ 代码


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
int n;
int a[1000007];
vector<int>r[1000007];
ll sum[10000007];
bool vis[1000007];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",a+i);
vis[a[i]]=1;
}
sort(a+1,a+n+1);
for(int i=1;i<=1000000;i++){
if(vis[i]==0)continue;
for(int j=i+i;j<=1000000;j+=i){
if(vis[j])r[j].push_back(i);
}
}
for(int i=2;i<=n;i++){
for(auto u:r[a[i]]){
if(vis[u])sum[a[i]]=(sum[a[i]]+sum[u]+1)%mod;
}
}
ll ans=0;
for(int i=1;i<=n;i++){
ans=(ans+sum[a[i]])%mod;
}
cout<<ans;
}

 类似资料: