首页 > 其他分享 >河南萌新联赛2024第(一)场

河南萌新联赛2024第(一)场

时间:2024-07-19 23:30:25浏览次数:17  
标签:frac 联赛 int ll cin 数组 2024 异或 萌新

先给出比赛链接:
https://ac.nowcoder.com/acm/contest/86639

A 造数

题目问多少次操作可以把0转为n

操作共有三种

  1. \(+1\)
  2. \(+2\)
  3. \(\times 2\)

能够发现操作的数字最大是2,那么这题就可以考虑二进制。三种操作就能这么理解:

  1. \(末位+1\)
  2. \(倒数第二位+1\)
  3. \(左移1位\)

那么我们就能把n转成2进制来求值
以n = 5为例
\(n = 5 = (101)_{2}\)

\( 0 \to 10 \to 100 \to 101 \)

可以发现,当当前位置为0时只需要1次操作就能填好这一位,当当前位置为1时则需要2次操作来填好这一位。

所以我们只需要把n转成二进制01串,然后遍历这个01串(注意不用遍历最高位,因为大于2时最优策略肯定是刚开始先+2)答案加上当前位再加1就行。(注意n为1时需要特判答案为1,为0时则不需要,因为不会进循环)

Show Code A

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    auto to2 = [&](ll n) {
        string res = "";
        while (n) {
            res += n % 2 + '0';
            n /= 2;
        }
        return res;
    };
    ll n = 0;
    cin >> n;
    if (n == 1) {
        cout << 1 << "\n";
    } else {
        int ans = 0;
        string s = to2(n);
        int len = s.size();
        for (int i = 0; i < len - 1; ++ i) {
            ans += 1 + (s[i] - '0');
        }
        cout << ans << "\n";
    }
}

D 小蓝的二进制询问

题目要求区间 [l,r] 中所有整数在二进制下1的个数之和并998244353取模。

对于一个1e18内的数,我们能log级别求出这个数各位上的1的个数
那能否快速求出这个数以内的各位上的1的个数呢?这样我们就能通过类似前缀和的操作来求出区间内的所有的1的个数了。
事实上是可以的
下面是0~16各个数以及它的二进制:(2进制左边为低位)

$ 10进制 $ $ 2进制 $
\(0\) \(000000\)
\(1\) \(100000\)
\(2\) \(010000\)
\(3\) \(110000\)
\(4\) \(001000\)
\(5\) \(101000\)
\(6\) \(011000\)
\(7\) \(111000\)
\(8\) \(000100\)
\(9\) \(100100\)
\(10\) \(010100\)
\(11\) \(110100\)
\(12\) \(001100\)
\(13\) \(101100\)
\(14\) \(011100\)
\(15\) \(111100\)
\(16\) \(000010\)

\[我们可以发现位权为2^{n}的位,以2^{n + 1}为循环 \]

那么我们就能快速的算出总共有几个循环,就能知道循环部分有多少个1了;再加上非循环部分就能知道1cur这一位上有多少个1了对每一位求和就能知道1cur各位上共有几个1了

但直接这么算由于数据太大很可能会爆ll(即超过ll能表示的数字上限),我们就可以对l - 1 , r分别进行拆位前缀和每一位都用1 ~ r当前位1的个数减去1 ~ l - 1当前位1的个数 再取模就不会爆ll了

Show Code D

constexpr ll mod = 998244353;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    vector p(63);
    p[0] = 1ll;
    for (int i = 1; i <= 62; ++ i) {
        p[i] = p[i - 1] * 2ll;
    }
    auto bitprefix = [&](ll n) { // 拆位前缀和
        vector res(64);
        for (int i = 0; i <= 61; ++ i) {
            if (n / p[i] % 2ll == 1ll) { // 当前位需要考虑非循环部分
                res[i] = (n + 1ll) / p[i + 1] * p[i + 1] / 2ll + (n + 1ll) % p[i];// 计算循环部分与非循环部分
            } else { // 当前位不需要考虑非循环部分
                res[i] = (n + 1ll) / p[i + 1] * p[i + 1] / 2ll; // 计算循环部分
            }
        }
        return res;
    };
    auto query = [&](ll l , ll r) {
        ll res = 0;
        vector sl = bitprefix(l - 1ll);
        vector sr = bitprefix(r);
        for (int i = 0; i <= 61; ++ i) {
            res += (sr[i] - sl[i]) % mod;
            res %= mod;
        }
        return res;
    };
    int tt = 1;
    cin >> tt;
    while (tt--) {
        ll l , r;
        cin >> l >> r;
        cout << query(l , r) << "\n";
    }
}

F 两难抉择新编

这题与H类似,但是x的上界缩小了,并且求的不是数组和了,而是数组异或和,即所有的数组元素异或和

异或及其性质

异或在C++中的运算符是 ^ 
异或可以理解为按位不进位加法
1.异或的逆运算就是异或本身 如果 a ^ b = c ,那么 c ^ b = a 

2.异或满足交换律 即 a ^ b == b ^ a
3.异或满足结合律 即 (a ^ b) ^ c == a ^ (b ^ c)
4.异或满足分配律 即 a ^ (b & c) == (a ^ b) & (a ^ c)
对于普通加法可以用高斯定律 sn = (1 + n) * n / 2 快速计算1~n的值 对于异或运算来说也有快速计算1~n各数的异或和的方法,即:
s(n)为1到n的数的异或和 s(n) = 1 , n % 4 == 1 s(n) = 0 , n % 4 == 3 s(n) = n , n % 4 == 0 s(n) = n + 1 , n % 4 == 2
代码实现如下: auto xorprefix = [&](ll n) { int flag = n % 4; if (flag == 0) { return n; } else if (flag == 1) { return 1; } else if (flag == 2) { return n + 1; } else if (flag == 3) { return 0; } };

根据异或的性质,我们并不能直接找到一个操作使得使得数组异或和最大
但是我们可以写出朴素的做法,即对每个数加或者乘可能的x的值算出此时的数组异或和。通过上面提到的异或的性质我们可以知道,当数组异或和为sumxor时,只需要 sumxor ^ a[i] 就能删掉数组中a[i]的贡献,此时再异或上a[i]改变的值就能求出此时的数组异或和,取最大就行了

然而其实这个朴素做法就能AC此题

\[注意x \in [1 , \lfloor n / i \rfloor] \]

这其实是一个比较常见的调和级数优化

\( \sum\limits_{i = 1}^{n} \sum\limits_{j = 1}^{\frac{n}{i}} 1 = \sum\limits_{i = 1}^{n} \frac{n}{i} = n \sum\limits_{i = 1}^{n} \frac{1}{i} < n(1 + ln(n)) \)

下面给出证明:

\( \int_{1}^{n} \frac{1}{x} = ln(x) \vert_{1}^{n} = ln(n) \)

通过图像法可知

\( \sum\limits_{i = 2}^{n} (i - (i - 1)) * \frac{1}{i} = \sum\limits_{i = 2}^{n} \frac{1}{i} < \int_{1}^{n} \frac{1}{x} = ln(x) \)

所以

\( \sum\limits_{i = 1}^{n} \frac{1}{i} < 1 + ln(x) \)

这个复杂度是可以容忍的

Show Code F

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    ll n , ans = 0 , sumxor = 0;
    cin >> n;
    vector a(n + 1);
    for (int i = 1; i <= n; ++ i) {
        cin >> a[i];
        sumxor ^= a[i];
    }
    for (int i = 1; i <= n; ++ i) {
        ll cur = sumxor;
        cur ^= a[i];
        for (int x = 1; x <= n / i; ++ x) {
            ans = max(ans , cur ^ (a[i] + x));
            ans = max(ans , cur ^ (a[i] * x));
        }
    }
    cout << ans << "\n";
}

H 两难抉择

这题让我们对数组进行操作来使得数组总和最大
共有两种操作:

\( 1.选择数组中的一个数使之加上x,~~~ x \in [1 , n] \)
\( 2.选择数组中的一个数使之乘上x,~~~ x \in [1 , n] \)

已知数组中元素是恒正的,那么要使数组和最大,且只能操作一次,对于操作1来说,自然是x选择n最大才能对数组的贡献最大(无论对哪个数加x贡献都一样);对于操作2来说,x选择最大的ai乘上n贡献最大

Show Code H

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    ll n;
    cin >> n;
    vector a(n);
    for (int i = 0; i < n; ++ i) cin >> a[i];
    sort(a.begin(),a.end());
    a[n - 1] = max(a[n - 1] + n , a[n - 1] * n);
    // 求和函数,for循环直接求也可以
    cout << accumulate(a.begin() , a.end() , 0ll) << "\n"; 
}

I 除法移位

题目要求最多t次循环右移,第几次操作使得数组的第一位元素除以其他所有元素的值最大
当第一个元素变大时,后面必有某个元素变小了,那么此时值一定大于变化前的值,所有我们只需要找到最多t次循环右移,元素的第一位何时最大就行。

Show Code I

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n , t;
    cin >> n >> t;
    vector a(n + 1);
    for (int i = 0; i < n; ++ i) cin >> a[i];
    a[n] = a[0];
    int maxn = 0 , maxi = 0 , cur = 0;
    for (int i = n; i >= 0 && cur <= t; -- i , ++ cur) {
        // 当有多种答案时,输出最小值,故不能取等号
        if (a[i] > maxn) { 
            maxn = a[i];
            maxi = cur;
        }
    }
    cout << maxi << "\n";
}

K 图上计数(easy)

你有一张 n 个点 m 条边的无向图,你有无数次删除操作来删除任意条边以获得若干个联通块。定义联通块的大小为其所包含点个数。定义这个图的代价是:你有任意次操作,每次操作合并两个联通块,合并后联通块大小为二者之和,最后剩下两个联通块大小的乘积为此图的代价,若只有一个则代价为0。你需要最大化此图代价。

因为你可以任意删边,也可以随意合并,那么就可以随意构造连通块了。

根据基本不等式链

\( H_{n} = \frac{n}{\sum\limits_{i = 1}^{n} \frac{1}{x_{i}}} = \frac{n}{ \frac{1}{x_{1}} + \frac{1}{x_{2}} + \dots + \frac{1}{x_{n}}} \)

\( G_{n} = \sqrt[n]{\prod\limits_{i = 1}^{n} x_{i}} = \sqrt[n]{x_{1} x_{2} \dots x_{n}} \)

\( A_{n} = \frac{1}{n} \sum\limits_{i = 1}^{n} x_{i} = \frac{ x_{1} + x_{2} + \dots + x_{n} }{n} \)

\( Q_{n} = \sqrt{ \frac{1}{n} \sum\limits_{i = 1}^{n} x_{i}^{2} } = \sqrt{ \frac{ x_{1}^{2} + x_{2}^{2} + \dots + x_{n}^{2} }{n} } \)

\[H_{x} \leq G_{x} \leq A_{x} \leq Q_{x} \]

已知连通块之和为定值,那么两个连通块大小越接近则,这两个连通块的乘积越大

即两个联通块相等或者相差仅为1的时候最大

Show Code K

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    ll n , m;
    cin >> n >> m;
    for (int i = 1; i <= m; ++ i) {
        int u , v;
        cin >> u >> v;
    }
    ll ans = ((n) / 2) * ((n + 1) / 2);
    cout << ans << "\n";
}

(PS:菜菜,目前只写了6题的题解)

标签:frac,联赛,int,ll,cin,数组,2024,异或,萌新
From: https://www.cnblogs.com/Proaes/p/18312275

相关文章

  • 干货 | 2024应用安全防护之云原生安全实践方案(免费下载)
    诚挚邀请您扫码加入以下信息安全精品资料知识星球,获取上万份安全PPT解决方案!!!感谢支持!!!......
  • 航电多校 2024 笔记
    01写点赛时不会的。难绷场,可能因为是01所以比较水,就只有最后一个能放省选模拟T1,以及一堆原神题。T5hdu7434博弈小马给出了一个可重小写字符集合 \(S\)。Alice初始时有空串 \(A\),Bob初始时有空串 \(B\)。两人轮流等概率取出集合 \(S\) 中的一个字符 \(c\),将它拼接......
  • 初级java每日一道面试题-2024年7月19日
    在Java中,重载(Overloading)和重写(Overriding)是面向对象编程中多态性的两个重要概念。1.重载(Overloading)定义:重载是指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可。也就是说,这些方法的名称相同,但参数的个数、类型或顺序至少有一个不同。目的:重载......
  • 循环位移(2024“钉耙编程”中国大学生算法设计超级联赛(1))
    #include<bits/stdc++.h>#defineendl'\n'usingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();constintN=4e6+7;constintP=131;ullp[N],an[N],bn[N];intn;voidinit(stringa,stringb){......
  • 最新2024视频剪辑Adobe全家桶AE,PR,PS软件等
    前言Adobe致力于为全球客户提供高品质、高性能的数字内容及相关服务,Adobe拥有卓越的产品、解决方案、服务和专业知识,帮助客户创造出与众不同、充满创意的产品和内容。Adobe拥有全球领先的数字化软件解决方案和行业知识产权(IP),为数字时代提供最具创新性、最高效的数字化创作工......
  • SMU Summer 2024 Contest Round 5
    SMUSummer2024ContestRound5RobotTakahashi思路按照Wi......
  • 2024.7.19模拟赛
    模拟赛T1立大功。T1yyylovesMathsVI(mode)摩尔投票法。既然有一个人出现次数\(\gt\frac{n}{2}\),那么我们可以用两两抵消的思路。最坏的情况就是每一个不是答案的都消掉了一个答案,但这样也会剩下正确答案。for(inti=1;i<=n;++i){ intx;scanf("%d",&x); if(cnt==......
  • (ECCV2024论文解读)GPSFormer: A Global Perception and Local Structure Fitting-based
    目录摘要1、引言2、方法2.1 背景3.2 全局感知模块2.3 局部结构拟合卷积泰勒级数局部结构拟合卷积显式结构引入2.4 GPSFormer点云分类部件分割任务3、实验3.13D形状分类ScanObjectNN数据集上的形状分类ModelNet40数据集上的形状分类3.2部件分割3.3小样本分类3.4消融研究全局感......
  • 2024“钉耙编程”中国大学生算法设计超级联赛(1)
    Preface唐完了的一集,被前中期题花式腐乳以至于中期一度被同校队伍打出\(n+3\)最后4h时堪堪写完8个题,最后1h冲刺众数那个题然后写一半方法假了直接下班当然还有个难绷的是传送那个题和我今年给新生拉的数据结构专题的一个题几乎一样,把代码拉来改下输入输入就过了,12min抢......
  • 学习Java的第五天(2024.7.18)
    1.字符串类:String类String类:是引用类型,默认值为null(注意不是空串"")字符串的声明:publicstaticvoidmain(String[]args){//声明字符串Stringstr="abc你好";System.out.println(str);str=newString("");//和strnewString();输出结果都......