Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final Round)

alice and cake

在这里插入图片描述
在这里插入图片描述

思路

  • 自顶向下模拟
  • 当前蛋糕最大值大于a最大值,那么需要切割该最大值。(如果不切最终结果一定不是a)
  • 当前蛋糕最大值等于a最大值那么两者一定可以匹配,然后考虑子问题即可。
  • 否则报错。


int main()
{
    int t;
    cin>>t;
    for(int i = 0;i<t;i++)
    {
        
        int n;
        cin>>n;
        priority_queue<ll,vector<ll>> q;
        priority_queue<ll,vector<ll>> p;
        ll sum = 0;
        for(int k =0;k<n;k++)
        {
            ll a;cin>>a;
            q.push(a);
            sum+=a;
        }
        p.push(sum);
        bool flag = true;
        while(!q.empty())
        {
           ll a = q.top();
           q.pop();
           ll b = p.top();
           p.pop();           
           if(a>b)
           {
               flag = false;break;
           }
           else if(a<b)   //继续切成两块
           {    
               q.push(a);     
               p.push(b/2);   //切成两块
               p.push(b-b/2);
           }
           //不能再切了,当前最大值匹配
        }
        if(flag&&q.empty()&&p.empty()) cout<<"YES"<<endl;
        else cout<<"NO"<<endl; 
    }
    system("pause");
}

D题Potion Brewing Class(前置知识缺乏)

在这里插入图片描述
在这里插入图片描述

思路

  • 每个点的最简分数形式。分母的最小公倍数就是答案
  • 如何求最小公倍数?考察每个分母的素数因子,对每个出现的素数因子的次数在所有分母中求最大值。最后的答案就是最小公倍数
  • 如何求解最大值?使用cnt维护即可。并预处理每个数的所有质因数

预处理所有数的质因数:

for(int i = 2;i<=200000;i++)
    {
        int t_1 = i;
        //对于t_1分解质因数
        for(int j = 2;j<=sqrt(i);j++)
        {
            while(t_1%j==0)
            {
                m[i][j]++;   //质因数加1
                t_1/=j;
            }
        }
        //不含有任何因子,本身是因数
        if(t_1>1)
            m[i][i]++;
    }

维护cnt。m[i][j]记录数i中素数j因子出现的次数。注意maximal只有在加的时候更新。

void dfs(int from,int st,map<int,int>m[200005],ll cnt[200005],vector<pair<int,pair<int,int>>> adjmap[],int n)
{
    for(pair<int,pair<int,int>> a:adjmap[st])
    {
        if(a.first!=from)
        {
            int v = a.first;
            //加上y的所有因子
            int y = a.second.second;
            int x = a.second.first;
            for(pair<int,int> b:m[x]) cnt[b.first]-=b.second;
            for(pair<int,int> b:m[y]) 
            {
                cnt[b.first]+=b.second;
                maximal[b.first] = max(maximal[b.first],cnt[b.first]);
            }
            //更新对应因子的最大值
            dfs(st,v,m,cnt,adjmap,n);
            for(pair<int,int> b:m[x]) cnt[b.first]+=b.second;
            for(pair<int,int> b:m[y]) 
            {
                cnt[b.first]-=b.second;
            }
        }
    }
    
}

最后只需使用cnt求出该最小公倍数。然后再dfs一次求出所有和。(使用带模计算模板类)。等补完一些基础知识再来。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值