牛客小白月赛23

https://ac.nowcoder.com/acm/contest/4784/B
B.阶乘
题意:给出一个正整数p 要你求一个最小的正整数n 使得 n的阶乘 为 p 的倍数

思路:先要知道 n的阶乘要为p的倍数 则等价于 n的阶乘中包含所有p的素因子个数 如果n的阶乘都包含了 大于n的阶乘就更不用说了 所以我们先对p进行质因数分解 然后遍历所有因子判断是否符合条件 二分即可

tip:用cin 加 long long 会T

#include <bits/stdc++.h>

using namespace std;

#define LL long long

const int N = 1e5+5;
int vis[N];

bool check(int x,int y)
{
    int cnt = 0;

    while(x)///计算该数中包含该因子的个数
    {
        cnt += x / y;
        x /= y;
    }

    return cnt >= vis[y];///大于等于p中该因子个数
}

int main()
{
    ios::sync_with_stdio(false);

    int t; cin >> t;

    while(t --)
    {
        int p;

        memset(vis,0,sizeof(vis));

        cin >> p;

        int n = p;

        for(int i = 2;i*i <= n;i ++)///质因数分解
        {
            while(p % i == 0)
            {
                p /= i;
                vis[i] ++ ;///对应因子数++
            }
        }

        int ma = p;

        for(int i = 2;i * i <= n;i ++)
        {
            if(n % i == 0 && vis[i])///若为p的因子
            {
                int l = 0;
                int r = 1e9;
                int x = 0;
                
                while(l + 1 < r)///二分符合条件的答案
                {
                    int mid = l + r >> 1;
                    if(check(mid,i))
                        r = mid,x = mid;
                    else
                        l = mid;
                }

                ma = max(ma,x);///取最大值 是一定要满足条件 即所有因子都要有
            }
        }

        cout << ma << '\n';
    }

    return 0;
}

E.A+B
在这里插入图片描述
输出样例即可 2^32次方

G.
在这里插入图片描述
思路:先计算每条边在答案中被加了多少次 dfs一下 然后升序排序 贪心把边权加上即可

#include <bits/stdc++.h>

using namespace std;

#define LL long long

const int N = 1e5+5;

vector <int> a[N];
int sz[N];

void dfs(int u,int v)
{
    sz[u] = 1;
    
    for(auto it : a[u])
    {
        if(it == v)
            continue;
        
        dfs(it,u);
        
        sz[u] += sz[it];
    }
}

int main()
{
    int n;
    
    cin >> n;
    
    for(int i = 1;i < n;i ++)
    {
        int u , v;
        
        cin >> u >> v;
        
        a[u].push_back(v);
        a[v].push_back(u);
    }
    
    dfs(1,1);
    
    for(int i = 1;i <= n;i ++)
        sz[i] = min(sz[i],n - sz[i]);
        
    sort(sz + 1,sz + 1 + n);
    
    LL sum = 1;
    LL res = 0;
    
    for(int i = n;i >= 2;i --)
        res += 1LL * sz[i] * (sum ++) * (n - sz[i]);
    
    cout << res << '\n';
    
    return 0;
}

H.
题意:给你n个数 能不能构成 2^30 次方
思路:只要和大于2^30次方 就一定可以 降序排序后贪心即可
证明懒得写了 嫖一嫖
在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;

#define LL long long

#define fi first
#define se second

const int N = 100004;

typedef pair <LL,LL> PLL;

PLL a[N];
LL vis[N];

int main()
{
    ios::sync_with_stdio(false);

    int t;

    cin >> t;

    while(t --)
    {
        int m;

        cin >> m;

        LL sum = 0;

        for(int i = 1;i <= m;i ++)
        {
            int x;

            cin >> x;

            a[i].fi = 1 << x;
            a[i].se = i;

            sum += a[i].fi;
        }

        if(sum < (1<<30))
        {
            cout << "impossible" << '\n';
            continue;
        }

        sort(a + 1,a + 1 + m,greater<PLL>());

        for(int i = 1;i <= m;i ++)
            vis[i] = 0;

        sum = 1 << 30;

        for(int i = 1;i <= m;i ++)
        {
            if(a[i].fi <= sum)
            {
                sum -= a[i].fi;
                vis[a[i].se] = 1;
            }
        }

        for(int i = 1;i <= m;i ++)
            cout << vis[i];
        cout << '\n';
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值