赞
踩
原题链接:https://atcoder.jp/contests/abc340/tasks/abc340_c
Time Limit: 2 sec / Memory Limit: 1024 MB
Score: 300 points
黑板上写着一个整数 N。
高桥将重复下面的一系列操作,直到所有不小于2的整数都从黑板上移除:
这里,⌊a⌋表示不大于a的最大整数,⌈a⌉表示不小于a的最小整数。
当不能再进行操作时,高桥支付的总金额是多少?
可以证明,无论操作的顺序如何,他支付的总金额是不变的。
3
5
下面是高桥如何执行操作的示例:
高桥为整个过程总共支付了3+2=5日元,因此打印5。
340
2888
100000000000000000
5655884811924144128
首先这个题目n非常大,肯定不能暴力,像这种题要么就是有什么规律,要么就是可以打表直接推出计算公式的,这个题目我当时是打表然后直接推出了计算公式做出来的,这个题目不难,但是我觉得有点意思,所以这里来说一下我的思路,我看了榜上有很多D,E都做出来了但是这个题目没做出来的,D纯纯最短路模板题,然后E区间维护(树状数组,线段树)模板题,没什么意思,这个C比D,E有意思多了,下面我贴一个我打表的图:
第一个图n=10,下面红色框框里面的每一行的和都是10,其他的图也是如此,这里我只列举了几个数据,那么对于任意的n的红色框框中会有几行呢,多打表几个数据会发现,n有几个因子2,那么就会有几行,那么这一部分的计算方式就是n*(row),row表示n的因子2的个数,那么对于红色框框的下面这一部分(也就是最后一行)怎么计算呢,我们可以知道的是最后一行有一部分1和一部分2,根据题意1属于无效数据,所以我们只需要关心最后一行有多少个2即可,实际上下面还有一行全是1,只是1是无效数据,这一行我就没列举出来了,最后一行的2实际上就是在一部分1上面加1,由于n的所有因子2在上面红色框操作结束之后到最后一行都会变成1,在最后一行1上面加1,实际上就是n除去所有因子2之后的余数,假设n有k个因子2,那么余数r=n-(2^k),那么这一部分会让r个1变为2,会有r*2的贡献,这一部分的计算方式就是r*2,那么总的计算公式就是n*row+r*2。
时间复杂度:计算n有多少个因子2,时间为O(logn)。
空间复杂度:O(1)。
cpp代码如下:
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
- typedef long long LL;
- LL n;
- int main()
- {
- cin >> n;
- LL v = 2;
- LL ans = 0;
- while (v <= n)
- {
- ans += n; //有多少个因子2就加多少个n
- v *= 2;
- }
- v /= 2; //上面求出来的是大于n的最小的2的幂,这里除以2就是小于等于n的最大的2的幂
- ans += 2ll * (n - v); //n-v就是余数了
- cout << ans << endl;
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。