暴力 + 贪心 --- 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,它可以变换得到的数字可以分为三类:

1.向左移动n位得到的数字;

2.向右移动n位得到的数字;

3.奇数/2后得到的偶数向右移动n位得到的数字。

 

处理一个数 Ai:


1、对 Ai 执行左移操作,记录 Ai 通过左移能够得到的数字,上限为1e5,vis 数组加1,cnt数组记录步数


2、对 Ai 执行右移操作,直到 Ai 为0.


若 Ai 的最低位为1,右移一步之后,进行左移,上限为1e5,维持vis数组和cnt数组.


若 Ai 的最低位为0,右移一步,维持vis数组和cnt数组.


这样我们就把一个数的所有情况都处理出来了,并且是最少的操作数.


最后遍历数组找 vis[i] 为n,并且操作数最小。

 

Time complexity: O(n*m*log(MAX))

 

Source code: 

 

复制代码
/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-07-15-18.53
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using namespace std;

const int MAXN(10+int(1e5));
int arrive_step[MAXN<<1];
int arrive_num[MAXN<<1];
int a[MAXN],n;

void init()
{
      for(int i=0; i<MAXN<<1; ++i) { arrive_step[i]=0,arrive_num[i]=0; }
}

inline void count_arrive(int &x)
{
      int t=x,step=0;
      arrive_num[t]++;
      while(t<=int(1e5))
      {
            t<<=1;
            step++;
            arrive_step[t]+=step;
            arrive_num[t]++;
      }
      t=x,step=0;
      while(t>1)
      {
            if(t!=1 && (t&1))
            {
                  int sta=t>>1;
                  int sstep=step+1;
                  while(sta<=int(1e5))
                  {
                        sta<<=1;
                        sstep++;
                        arrive_step[sta]+=sstep;
                        arrive_num[sta]++;
                  }
            }
            t>>=1;
            step++;
            arrive_step[t]+=step;
            arrive_num[t]++;
      }
}

int main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(0);
      while(~scanf("%d",&n))
      {
            init();
            for(int i=0; i<n; ++i)
            {
                  scanf("%d",&a[i]);
                  count_arrive(a[i]);
            }
            int ans=INT_MAX;
            for(int i=1; i<(MAXN<<1); ++i)
            {
                  if(arrive_num[i]==n)
                        ans=ans<arrive_step[i]?ans:arrive_step[i];
            }
            printf("%d\n",ans);
      }
      return 0;
}
/*

*/
复制代码

 

posted @   北岛知寒  阅读(514)  评论(2编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示
主题色彩