首页 > 其他 > 详细

1483 化学变换 乱搞题

时间:2017-02-12 01:09:26      阅读:348      评论:0      收藏:0      [点我收藏+]

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1483

首先,要知道在0---4e5内的体积下,一定存在答案。不会存在一些更大的答案。(要证明我也不晓得,我直觉)

那么我的思路就是,枚举,0--4e5,然后需要O(1)判断和更新答案。

那么预处理isok[cnt]表示产生cnt这个数字,其中有两个参数,has,表示一共有多少个数能产生这个数字。那么明显has需要等于n,才是答案的贡献。然后step,表示这n个数产生cnt这个数字,需要的步数的总和。这个可以用dfs维护。每次要么 * 2,要么 / 2,产生相同的数字,就可以return了、最优的复杂度是偶数的情况,是logn。奇数的话,也就多了几个常数,因为 / 2多次(应该不超过3次),都会变成偶数

技术分享
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e5 + 20;
int mx;
struct node {
    int step;
    int has;
}isok[maxn * 4];
int vis[maxn * 4];
int DFN;
void calc(int x, int cnt) {
    if (x >= mx) return;
    if (vis[x] == DFN) return ;
    vis[x] = DFN;
    isok[x].step += cnt;
    isok[x].has++;
    calc(x * 2, cnt + 1);
    calc(x / 2, cnt + 1);
}
void work() {
    int n;
    scanf("%d", &n);
    mx = 4e5;
    for (int i = 1; i <= n; ++i) {
        int x;
        DFN++;
        scanf("%d", &x);
        calc(x, 0);
    }
    int ans = inf;
    for (int i = 0; i <= mx; ++i) {
        if (isok[i].has != n) continue;
        ans = min(ans, isok[i].step);
    }
    cout << ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code

 

1483 化学变换 乱搞题

原文:http://www.cnblogs.com/liuweimingcprogram/p/6390284.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!