首页 > 其他分享 >Codeforces Global Round 27,D. Yet Another Real Number Problem 题解

Codeforces Global Round 27,D. Yet Another Real Number Problem 题解

时间:2024-10-30 22:16:20浏览次数:6  
标签:Real 27 前缀 前面 题解 ll rem ans mod

单调栈+贪心

  • 题意:给定一个序列从左往右对于每个索引 i i i,求出其前缀的数组可以进行任意次以下操作的条件下:选择 j < = k 且 k < = i 且 a j m o d    2 = 0 ,令 a k = a k ∗ 2 , a j = a j / 2 j<=k且k<=i且a_j \mod 2 = 0,令a_k=a_k*2,a_j=a_j/2 j<=k且k<=i且aj​mod2=0,令ak​=ak​∗2,aj​=aj​/2,可能获得的最大前缀和
  • 每一个数只能从它的前面获得乘以2的次数,这很重要,考虑下面的一个序列
    • 原数列: 4 2 5 2 7
    • 能除则除2后:1 1 3 1 7
    • 数组下标从1开始,假如目前遍历到 i = 3 i = 3 i=3,我们肯定是想要把前面所有的乘2次数都贪心的乘给3,因为3最大,这样可以使每个乘2有更大的收益;再遍历到 i = 5 i = 5 i=5呢?首先,对于 i = 3 → 5 i=3\to5 i=3→5之间的乘2次数,我们给不了3去乘,那显然给7去乘,乘了之后,我们发现 7 → 14 7\to14 7→14,那对于 i = 3 i=3 i=3前面的2,我们是不是应该乘给这个14,这样乘2的收益更大;再假设 i = 5 i=5 i=5时 a 5 = 1 a_5=1 a5​=1,这个时候我们用掉3~5之间的2之后, a 5 = 2 a_5=2 a5​=2, a 3 > a 5 a_3>a_5 a3​>a5​的,这个时候 i = 3 i=3 i=3前面的2肯定乘给 a 3 a_3 a3​更优
    • 这时候我们发现,这个过程类似维护一个单调的东西,只有后面的区间的乘2利用完之后能够得到一个大于之前的那个获得前面部分乘2的那个数,我们才会把前面部分的乘2给这个新的数,这个时候这个新的数又成为了一个新的”卫兵“,守住前面的乘2
    • 可以用单调栈维护这个过程,使得栈顶元素的 b t o p ∗ 2 c [ t o p ] − c [ p r e ] b_{top}*2^{c[top]-c[pre]} btop​∗2c[top]−c[pre]是栈中最大的,其中 b b b数组表示除2后的序列数, c c c数组表示乘2次数的前缀和,每次对于 i i i,维护这个栈顶是否要弹出,弹出这一操作就是上面例子的第一个情况,随时维护答案 a n s ans ans,弹出栈需要减去贡献,每个 i i i加入都要计算新的贡献
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve()
{
    const ll mod = 1e9 + 7;
    int n;
    cin >> n;
    vector<ll> a(n + 1), b(n + 1), p_rem(n + 1), c(n + 1);
    // p_rem 记录前面都除以2之后的剩余数的前缀和
    // c统计除以2的次数(前缀)
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        b[i] = a[i];
        while (b[i] % 2 == 0)
        {
            b[i] /= 2;
            c[i]++;
        }
        c[i] += c[i - 1];
        p_rem[i] = (p_rem[i - 1] + b[i]) % mod;
    }

    auto ksm = [&](ll a, ll b) -> ll
    {
        ll ans = 1;
        while (b)
        {
            if (b & 1)
                ans = ans * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return ans % mod;
    };

    auto cmp = [&](ll a, ll b, ll c) -> bool
    {
        if (c >= 30) // 大于1e9,直接不用比了
            return true;
        return a <= b * (1LL << c);
    };

    // 单调栈
    stack<ll> st; // 应该存上一个终点的坐标
    ll sum = 0;
    for (int i = 1; i <= n; i++)
    {
        // 维护单调栈
        while (!st.empty() && cmp(b[st.top()], b[i], c[i] - c[st.top()]))
        {
            // 如果更优,删掉之前的区间的贡献
            int lst = 0, now = st.top();
            st.pop();
            if (st.size())
                lst = st.top();
            sum -= (b[now] * ksm(2, c[now] - c[lst]) - b[now]);
        }
        if (st.size()) // 加上当前贡献
            sum += b[i] * ksm(2, c[i] - c[st.top()]) - b[i];
        else
            sum += b[i] * ksm(2, c[i]) - b[i];
        st.push(i);
        cout << (sum % mod + p_rem[i] + mod) % mod << " ";
    }
    cout << '\n';
}

signed main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--)
        solve();
    cout << endl;
    // system("pause");
    return 0;
}

标签:Real,27,前缀,前面,题解,ll,rem,ans,mod
From: https://blog.csdn.net/2301_81388123/article/details/143376676

相关文章

  • 2024CCPC哈尔滨部分题解
    赛时被评测机卡死了M.奇怪的上取整求\(\sum_{i=1}^{n}f(n,i)\)\(Input\)第一行一个整数\(T(1<=T<=10^3)\),表示数据组数对于每组数据,一行一个整数\(n(1<=n<=10^9)\)\(Output\)对于每组数据,输出一行一个整数,表示答案。\(Sample\)35451114514————————21T10......
  • Apache Commons Net 共享SSLSession问题解决
        某些服务器会默认开启TLS会话恢复,如FileZillaServer1.0及以后的版本(相对于1.0以前版本就是先当与勾选了RequireTLSsessionresumptionondataconnectwhenusingPORTP)。ApacheCommonsNet目前是不支持TLS会话恢复的,所以我们只能通过重写FTPSClient来实现。不然你......
  • ZZJC新生训练赛第十二场题解
    难度分类(同一难度下按字典序上升)入门:G简单:C,E,A中等:F,D,B困难:HG-解题思路按照题意模拟即可G-代码实现#include<bits/stdc++.h>intmain(){std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::strings;......
  • 周报 | 24.10.21-24.10.27文章汇总
    为了更好地整理文章和发表接下来的文章,以后每周都汇总一份周报。周报|24.10.14-24.10.20文章汇总-CSDN博客OpenCV学堂|YOLOv8实战|荧光显微镜细胞图像检测-CSDN博客江大白|通用视觉Backbone,TransXNet:全局+局部动态=性能强大(附源码及源码)-CSDN博客OpenMMLab|S4模......
  • springboot停车系统-计算机毕业设计源码27192
    摘 要随着城市化进程的不断加快和汽车保有量的持续增加,城市停车难题成为居民生活中的一大挑战。针对停车资源紧张、停车管理效率低下等问题,智能停车系统应运而生。本研究旨在探讨基于安卓平台的停车系统的设计与实现,利用Java编程语言、MySQL数据库和SpringBoot框架,为用户提......
  • P7408 [JOI 2021 Final] 地牢 3 题解
    Description有一个\(N+1\)层的地牢,在地牢里有\(M\)个玩家。地牢的每层从入口开始,用\(1\)到\(N+1\)的整数编号。玩家从\(1\)到\(M\)标号。玩家使用能量从一层移动到下一层。玩家从第\(i\(1\lei\leN)\)层移动到第\(i+1\)层所用的能量为\(A_i\)。因为这是一个......
  • CF1187题解
    前言这套题相对来讲难度不算高,并且质量也很好,建议尝试CF1187A一眼秒,但我没有考虑s,t只有这一种排列方式,所以取一下\(max(n-s,n-t)\)#include<bits/stdc++.h>usingnamespacestd;intT,n,s,t;intmain(){ scanf("%d",&T); while(T--){ scanf("%d%d%d",&n,&s,&t)......
  • 动态规划题解报告
    Findacar注意到矩阵本质上是一个分形,即每次向右下复制当前矩阵,证明考虑归纳法。由此可以知道一个比较好的性质\(a_{i+k,j+k}=a_{i,j}\)其中\(k=2^n\),由于每次是复制加倍,所以横纵坐标都会加上一个\(2^n\),且每次增加的二次幂一定是横纵坐标二进制减一后没有的那一位(证明考虑......
  • CF2030 题解
    因为cf炸了所以没办法提供代码,抱歉喵。A给定序列,定义$mn_i=\min_{j\lei}a_j,mx_i=\max_{j\lei}a_j$。重排该序列,最大化$\sum_{i=1}^nmx_i-mn_i$。$n\le10^5$正解手玩出一个构造,把最大和最小值放在前两个位置,这样的价值是\((n-1)\times(mx-mn)\)。由于\(m......
  • 天眼销常见问题解答
    天眼销上线已经有一段时间了,用户在此期间提出了一些问题。经过我们的整理在这里为大家解答。回答问题整理1.你们的数据来源是哪?精确吗?本平台的企业数据来源于全网公开数据,包含全国企业信用信息公示系统,其中企业联系方式主要来源于全国企业信用信息公示系统中的公示的......