网易笔试20220904

T1

题意:统计取模之后出现最多的数

思路:没啥好说的

T2

题意:给n,k,t,要求构造长度为n含有k个1以及有恰好t对相邻1的01串,无法满足则返回-1

思路:可以得出,k个1最多组成k-1对相邻1(连续k个1),最少则是k-1 - (n-k),t在这个范围之内可以通过把0依次插入连续的1之间来构造得到(每插入一个0减少一个相邻对1)

int main() {
    int n,k,t;
    cin>>n>>k>>t;
    if (t <= k-1 && k <= n && k-1-t <= n-k){
        string s = "";
        int p = k-1 - t;
        while(p--){
            s += "10";
        }
        p = k - (k-1-t);
        while(p--){s+="1";}
        p = n-k - (k-1-t);
        while(p--){s+="0";}
        cout<<s;
    }
    else cout<<-1;
}

T3

题意:给x,k和一个长度为n的数组a(输入均为正整数),每次可以选取一个元素-x,问经过k次操作之后能够得到的数组最小的最大值

思路:O(n)验证一个答案,容易想到二分+验证来找到解。需要注意的是验证答案的时候把k刚好用完不一定是最优解,应该按照剩下的k>=0算合法解来逼近最优解

typedef long long ll;
ll a[100005];
int n;
ll k, x;
bool check(ll target)
{
    ll tmp = k;
    for (int i = 0; i < n; ++i)
    {
        tmp -= max(0LL, ((a[i] - target) + x - 1) / x);
        if (tmp < 0)
            return false;
    }
    if (tmp >= 0)
        return true;
    return false;
}

int main()
{

    cin >> n >> k >> x;
    ll maxx = 0;
    for (int i = 0; i < n; ++i)
    {
        cin >> a[i];
        maxx = max(a[i], maxx);
    }

    ll l = maxx - k * x, r = maxx;
    ll mid;
    while (l <= r)
    {
        mid = (l + r) >> 1;
        if (check(mid))
        {
            r = mid - 1;
        }
        else
            l = mid + 1;
    }
    cout << l;
}

T4

Hard的一题,写了1h+还是没写出来,太菜了。。。

题意:给一颗有根树,每个结点有权值。每个子树的答案定义为该子树每个结点的权值的积的因数个数,求统计所有子树的答案之和(取模1e9+7)

思路:

假设n的质因数分解为
因数个数则为
又有

对于一个子树的根结点,该子树的权值乘积可以通过根结点的权值乘以每个孩子的子树权值乘积来递归地得到,因此在递归的过程中维护一个质因数列表(我用一个unordered_map实现),当前子树的质因数列表可以通过当前根结点权值的质因数列表再加上每个孩子的质因数列表得到,通过该质因数列表计算答案,便可递归地求解。

但是写完了最后只过了5%,不知道错在哪里

typedef long long ll;
int a[100005];
vector<int> E[100005];
const ll mod = 1e9 + 7;
ll total_ans = 0;
bool used_pri[100005];
bool used[100005];
vector<ll> prime;
unordered_map<int, ll> dfs(int rt)
{
    // answer of this subtree
    unordered_map<int, ll> ma;
    // prime factorize
    int tmp = a[rt];
    for (auto pri : prime)
    {
        if (!used_pri[tmp])
        {
            ma[tmp] = 1;
            break;
        }

        if (tmp % pri == 0)
        {
            ma[pri] = 0;
            while (tmp % pri == 0)
            {
                tmp /= pri;
                ++ma[pri];
            }
        }
        if (tmp < pri)
            break;
    }

    // count the answer of subtree
    used[rt] = 1;
    for (int v : E[rt])
        if (!used[v])
        {
            auto &&ans_son = dfs(v);
            for (const auto &item : ans_son)
            {
                if (ma.count(item.first))
                    ma[item.first] = (ma[item.first] + item.second) % mod;
                else
                    ma.insert(item);
            }
        }

    // count total ans
    ll tmp_ans = 1;
    for (const auto &item : ma)
    {
        tmp_ans = tmp_ans * ((item.second + 1) % mod) % mod;
    }

    total_ans = (total_ans + tmp_ans) % mod;
    return ma;
}
int main()
{
    // Linear sieve prime
    memset(used_pri, 0, sizeof used_pri);
    used_pri[0] = 1;
    used_pri[1] = 1;
    for (int i = 2; i <= 100000; ++i)
    {
        if (!used_pri[i])
            prime.push_back(i);
        for (int j = 0; i * prime[j] <= 100000LL && j < prime.size(); ++j)
        {
            used_pri[i * prime[j]] = 1;
            if (!i % prime[j])
                break;
        }
    }

    int n;
    cin >> n;
    for (int i = 0; i < n; ++i)
    {
        cin >> a[i];
        used[i] = 0;
        E[i].clear();
    }
    for (int i = 0; i < n - 1; ++i)
    {
        int u, v;
        cin >> u >> v;
        E[u - 1].push_back(v - 1);
    }
    total_ans = 0;
    dfs(0);
    cout << total_ans;
}
#网易笔试#
全部评论
我觉得T3的关键点就是在于check函数,当程序二分找数时,寻找的目标是找到那么一个数,首先它需要尽量小于V[i],但是这个数也需要保证与V[i]之间减去x的这种操作次数尽量少。由此一次次查找,找到的数就是答案。这只是我的理解哦
点赞 回复 分享
发布于 2022-09-06 22:15 浙江
厉害
点赞 回复 分享
发布于 2022-09-04 21:30 吉林
启发式合并会超时,用动态开点线段树就好了
点赞 回复 分享
发布于 2022-09-04 23:05 湖南
hi~同学,秋招遇“寒气”,牛客送温暖啦!23届秋招笔面经有奖征集中,参与就得牛客会员7天免费体验,最高赢300元京东卡!戳我去看>>>https://www.nowcoder.com/link/zhengjipinglun
点赞 回复 分享
发布于 2022-09-05 13:12 北京
太厉害大佬
点赞 回复 分享
发布于 2022-09-06 21:50 浙江
第三题维护一个大根堆贪心也可以,可能更简单
点赞 回复 分享
发布于 2022-09-17 13:21 北京

相关推荐

评论
1
12
分享

创作者周榜

更多
牛客网
牛客企业服务