51nod 1596搬货物 解题报告

题目链接:51nod 1596搬货物

这一题把我恶心到了,连续T了6次,最后500+ms过了

先说解题思路吧,每个物品质量都是2的幂,质量和为2的幂的物体可以一起搬。假设有一个物体质量为2^x,它和另一件质量为2^y的物体能一起搬,那么也就是说存在z满足2^z =2^x+2^y,可设y =  x * 2^w,z = x*2^u,也就是x * 2^u = x*1 + x*2^w,得到2^u = 1 + 2^w,这个就很明显了,w=0,u=1。也就是说两个质量一样的可以一起搬,然后两个质量为x的又可以和一个质量为2*x的一起搬,这么一来,递推式就出来了。

于是我们就可以T了(我就是这么直接写的,然后1e6的规模的O(n)复杂度,T了),就是这么诡异。想了半天也没弄懂为什么会T,最后想到了以前看到过的读入挂,在输入规模超过1e5的情况,用scanf输入就很可能T,于是就有了读入挂这玩意儿。读入挂,顾名思义给读入开挂。

我们知道C++为了兼容C语言的标准输入输出,使得cin和cout速度变得很慢,比scanf慢十倍,这时就可以用cin.tie(0)和ios::sync_with_stdio(0)来加速,这样一来就不能用scanf和printf了,具体的这里就不详细说明了,有兴趣的可以百度看看,但经过测试,这样在OJ上还是比scanf慢。于是以C++为主的ACMer习惯性的用scanf进行输入。然而,在这里要说的是读入挂,目前我知道的C语言(C++)输入最快的方式,使用getchar()读取,然后手动进行转换。下述代码中的read()就是int读入挂:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int maxn = 1e6+32;
int a[maxn];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9')   {ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x;
}
int main()
{
    int n;
//    freopen("51nod_Problem_1596_Test_13_In.txt", "r", stdin);
//    freopen("in.txt", "r", stdin);
    n = read();
    for(int x, i = 0; i < n; ++ i)
    {
        x = read();
        a[x] ++;
    }
    for(int i = 0; i < maxn; ++ i)
        a[i+1] += (a[i] >> 1), a[i] &= 1;
    int sum = 0;
    for(int i = 0; i < maxn; ++ i)
        sum += a[i];
    printf("%d\n", sum);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/q1410136042/article/details/76612934