cf#312-C - Amr and Chemistry-枚举


http://codeforces.com/contest/558/problem/C


每次操作  把a[i] ,/2取整或者X2,求min操作次数 使得所有的数一样


n和数的最大值 都是 1e5

这里 暴力枚举一下每个数字的情况即可

开一个vis[]

对于一个数x,每次/2都 做一轮 【 不断*2的操作 ,  对于每次得到的一个数,vis[y]++,并且 step[y]+=步数】

这样就把每个数 所能变成的所有数,都枚举出来了,并且记下最早出现的那个步数



最后遍历一次1-maxn, 找到出现次数为n的 数中 所用步数最少的


一开始枚举每个数的所有情况时,用了set判重。。。TLE。。。。换成数组就78MS了.....

看来还是。。。



#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;

__int64 ss[100005];
__int64 mark[111144*2];
__int64 vis[111144*2]; 
__int64 vis_num[111144*2]; 
int main()
{
	__int64 n,i; 
	
	scanf("%I64d",&n);
	for (i=1;i<=n;i++)
	{
		scanf("%I64d",&ss[i]);
	}
	__int64 ppp=100000;__int64 k;
	for (k=1;k<=n;k++)
	{
		int cun=0; 
		__int64 tt=ss[k];
		while(tt)
		{ 
				vis[tt]++;
				mark[tt]+=cun;
				vis_num[tt]=k;
				__int64 tmp=tt;
				int tmp_cun=cun;
				while((tmp<<1)<=ppp)
				{
					tmp_cun++;
					tmp<<=1; 
				if (vis_num[tmp]==k) break;  
					vis[tmp]++;
					mark[tmp]+=tmp_cun;
					vis_num[tmp]=k;
				} 
				tt>>=1;
				cun++; 
		}
	}
	__int64 minn=922337036854775807;
	for (i=1;i<=100000;i++)
	{
		if (vis[i]!=n) continue;
		if (mark[i]<minn)
			minn=mark[i];//,printf("%I64d--%I64d\n",mark[i],i);
		
	}
	printf("%I64d\n",minn);

	return 0;

}



你可能感兴趣的:(cf#312-C - Amr and Chemistry-枚举)