Amr and Chemistry---cf558C(暴力,加技巧)

题目链接:http://codeforces.com/problemset/problem/558/C

题意:有n个数,每个数都可以进行两个操作 *2 或者 /2,求最小的操作次数和,使得所有的数都相等;

计算一下时间复杂度可以知道每个数所能达到数的时间复杂度是log(1e5)最终的时间复杂度也就是 nlog(1e5), 所以暴力能过,

刚开始看到的时候一看数据范围就根本不敢暴力了。。。

我们可以把每个数所有变化情况都记录下来,并记录出现的次数,因为只有用1e5的数据量。

先把数据量范围内的所有比a1大的数(a1*2,a1*4。。。)的次数都相对应的加(1,2,。。。)

然后找比a1小的,/2如果遇到奇数,还要接着往上*2.。。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define N 100100
#define INF 0x3f3f3f3f
#define met(a, b) memset(a, b, sizeof(a))
using namespace std;

int  num[N], cnt[N];

void F(int x)
{
    int step = 0, t = x;

    cnt[x] ++;

    while(t*2 < N)///往上*2得到的都是偶数,直接记录;
    {
        t = t*2;
        step ++;
        num[t] += step;
        cnt[t] ++;
    }

    t = x, step = 0;

    while(t > 1)
    {
        if(t!=1 && t%2==1)///往下/2得到的可能是奇数, 如果是奇数的话继续往上*2;
        {
            int y = t/2;
            int step0 = step+1;
            while(y*2 < N)
            {
                y = y*2;
                step0 ++;
                num[y] += step0;
                cnt[y] ++;
            }
        }
        t = t/2;
        step ++;
        num[t] += step;
        cnt[t] ++;
    }
}

int main()
{
    int n, x;
    while(scanf("%d", &n)!=EOF)
    {
        met(cnt, 0);
        met(num, 0);
        for(int i=0; i<n; i++)
        {
            scanf("%d", &x);
            F( x );
        }
        int ans = INF;
        for(int i=0; i<N; i++)
        {
            if(n == cnt[i])
                ans = min(ans, num[i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}

时间: 2024-10-24 00:15:17

Amr and Chemistry---cf558C(暴力,加技巧)的相关文章

Codeforces Round #312 (Div. 2)——C暴力技巧——Amr and Chemistry

Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals

暴力 + 贪心 --- Codeforces 558C : Amr and Chemistry

C. Amr and Chemistry Problem's Link: http://codeforces.com/problemset/problem/558/C Mean: 给出n个数,让你通过下面两种操作,把它们转换为同一个数.求最少的操作数. 1.ai = ai*2 2.ai = ai/2 (向下取整) analyse: 基本思路:首先枚举出每个数能够到达的数字并且记录下到达该数组需要的步数,然后从到达次数为n次的数字中选择步数最小的即为答案. 对于一个数字Ai,它可以变换得到的数字可

CodeForces 558 C. Amr and Chemistry &amp;&amp; 51NOD 1483 化学变换(暴力 + 贪心)

传送门 Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemic

CF 558 C. Amr and Chemistry 暴力+二进制

链接:http://codeforces.com/problemset/problem/558/C C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Amr loves Chemistry, and specially doing experiments. He is preparing

Codeforces 558C Amr and Chemistry(数论+位运算)

C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n differ

Codeforces Round #312 (Div. 2) C.Amr and Chemistry

Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals

codeforces 558 C Amr and Chemistry

预处理两个数组: vis[x],有几个数能够变成x num[x],所有数变成x最少需要变化的步数 ans=min(num[x]),vis[x]==n #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector>

Codeforces 558C Amr and Chemistry 全都变相等

 题意:给定一个数列,每次操作仅仅能将某个数乘以2或者除以2(向下取整). 求最小的操作次数使得全部的数都变为同样值. 比赛的时候最后没实现.唉.之后才A掉.開始一直在想二分次数,可是半天想不出怎么推断.后来发现事实上每一个数都能变成的数非常少非常少(最多400个不到).于是想到用数学方法+一点暴力,可惜时间不够了. 也不能全然算是数论题.仅仅是用到了一些数学思想.须要一点预处理,后面的计算中还会用到二分的技巧. 对某个数n,设n = s*2^r(当中s为奇数),则n能变成这样一些数:s*2

Codeforces Amr and Chemistry(数学+乱搞)

题意:给n个数,每个数每次可以乘二或除以二(向下取整相当于左移或右移),问最少经过多少次操作可以使这n个数变相等. 思路:首先考虑每个数的可能取值,将一个数表示成s*2^k的形式,s是奇数. 那么这个数的所有可能取值为s'*2^x,(s'=s/2,(s/2)/2,.....)且s'*2^x<=100000 因为这题数据范围不大,而且每个值可能的取值不多最多几百个,所以记录1到100000每个值可能被取到的次数以及总操作数,最后从1遍历到100000取最小的ans即可 ps:个人赛这道题做了一下午