CF 558C Amr and Chemistry 思维,二进制

本文探讨了一个算法问题:如何通过最少的操作使序列中的所有元素相等。操作包括将元素乘以2或除以2(向下取整)。文章给出了详细的解决思路与实现代码,包括如何计算最优操作次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:长度为n的序列a,操作1:将某个a[i]*2.操作2:将某个a[i]/2(下取整).
n,a[i]<=1e5.问最少需要多少次操作能使得序列a的数都相同?




最后的数肯定不会超过序列中的最大值mx,
若y>mx 那么每个元素的最后一次操作肯定是*2=y>mx,此时去掉乘2操作,操作数减小,数列的数还是相等


操作每次都是乘以或者除以2[下取整]
19-10-5-2
19-10-20-40
19-10-5-2-4-8-...
除法由奇数变为偶数时,此时进行乘法能变到新的数.
也就是二进制最低位如果为1,那么此时/2后*2得到新的数和原来不同.


最大数的二进制位数为m,最坏情况下bit都为1,则最多生成m*(m+1)/2新的数(每次操作后都是前缀为11..开头的数).

计算f[i]:表示前k个数变成i的最小价值即可.O(n*m*(m+1)/2)

#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5,inf=0x3f3f3f3f;
int n,a[N],f[N],h[N]; 
void calc(int x,int cnt)
{
	int mx=3e5;
	while(x<=mx)
	{
		f[x]+=cnt,h[x]++;
		x*=2;
		cnt++;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
//	freopen("1.txt","r",stdin);
	memset(f,0,sizeof(f));
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		h[a[i]]++;
		calc(a[i]*2,1);
		int cnt=1,num;
		while(a[i])
		{
			if(a[i]!=1&&a[i]%2)
				calc(a[i]/2*2,cnt+1);
			a[i]/=2;
			f[a[i]]+=cnt,h[a[i]]++;
			cnt++;
		}
	}
	int res=inf;
	for(int i=1;i<N;i++)
		if(h[i]==n)
			res=min(res,f[i]);
	cout<<res<<'\n';
	return 0;
}

标程:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cctype>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <sstream>
#include <cmath>
#include <limits>
#include <utility>
#include <iomanip>
#include <set>
#include <numeric>
#include <cassert>
#include <ctime>
 
#define INF_MAX 2147483647
#define INF_MIN -2147483647
#define INF_LL 9223372036854775807LL
#define INF 2000000000
#define PI acos(-1.0)
#define EPS 1e-8
#define LL long long
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define f first
#define s second
#define setzero(a) memset(a,0,sizeof(a))
#define setdp(a) memset(a,-1,sizeof(a))
#define bits(a) __builtin_popcount(a)
 
using namespace std;
 
int cnt[100005], vis[100005], steps[100005];
 
int main()
{
  //ios_base::sync_with_stdio(0);
  //freopen("lca.in", "r", stdin);
  //freopen("lca.out", "w", stdout);
  int n, res = INF, x, y;
  scanf("%d", &n);
  for(int i=1;i<=n;i++)
  {
    scanf("%d", &x);
    queue<pair<int, int> > q;
    q.push(mp(x, 0));
    while(!q.empty())
    {
      x = q.front().f;
      y = q.front().s;
      q.pop();
      if(x > 100003) continue;
      if(vis[x] == i) continue;
      vis[x] = i;
      steps[x]+=y;
      cnt[x]++;
      q.push(mp(x * 2, y + 1));
      q.push(mp(x / 2, y + 1));
    }
  }
  for(int i=0;i<=100000;i++)
    if(cnt[i] == n)
      if(res > steps[i])
        res = steps[i];
  printf("%d", res);
  return 0;
}


<think>嗯,用户的问题是关于解决MPP context初始化失败和解码器打开错误的问题,具体错误是“Failed to init MPP context and open decoder h264 error -1 wrapped_avframe filtergraph initialization issue”。我需要根据提供的引用资料来寻找可能的解决方案。 首先,查看引用[1]和[2],里面提到了MPP_CTX_DEC用于解码,编解码格式如H.264对应的MPP_VIDEO_CodingAVC。用户用的是h264解码器,可能需要确认是否正确设置了这些参数。比如,是否正确初始化了MPP context为解码模式,编码格式是否正确设置为H.264。如果参数设置错误,可能导致初始化失败。 接下来,引用[3]提到了MPICH初始化线程时GPU初始化失败的问题。虽然用户的问题不是直接关于MPICH,但可能涉及硬件加速或GPU相关的配置。比如,检查系统是否支持硬件解码,驱动是否正确安装,或者MPP是否配置为使用正确的硬件加速接口。 然后,引用[4]提到FFmpeg的h264_mp4toannexb过滤器,用于将MP4格式的H.264转换为Annex B格式,因为解码器可能需要起始码。如果输入的视频流格式不符合解码器的要求,比如没有起始码或者SPS/PPS信息缺失,可能导致解码器无法初始化。这时候需要检查输入数据的格式是否正确,是否需要添加过滤器进行转换。 可能的解决方案步骤包括: 1. 确认MPP context初始化为解码模式(MPP_CTX_DEC)并使用正确的编码格式(MPP_VIDEO_CodingAVC)。 2. 检查硬件支持,确保驱动和固件版本兼容,可能需要更新或配置环境。 3. 验证输入数据格式,可能需要使用h264_mp4toannexb过滤器转换格式。 4. 检查错误代码-1的具体含义,可能需要查阅MPP文档或日志来获取更详细的错误信息。 5. 确保系统资源足够,比如内存或权限问题导致初始化失败。 另外,用户提到的wrapped_avframe问题可能涉及帧处理流程,需要检查filtergraph的配置是否正确,数据是否正确地传递到解码器。可能需要检查FFmpeg的过滤器链配置,确保每个步骤衔接正确,特别是格式转换部分。 最后,建议用户检查代码中的参数设置,添加详细的日志输出,以便定位具体的失败步骤。同时,参考MPP和FFmpeg的官方文档,确认使用的API和流程是否符合最新版本的要求。</think>### MPP context初始化失败与解码器错误解决方案 #### 1. 检查编解码参数配置 - **MPP上下文类型**:确认初始化时设置`MPP_CTX_DEC`用于解码,若错误设置为`MPP_CTX_ENC`会导致初始化失败[^2]。 - **编码格式匹配**:H.264解码需指定`MPP_VIDEO_CodingAVC`,HEVC对应`MPP_VIDEO_CodingHEVC`。错误格式会导致`error -1`[^1][^2]。 - **代码示例验证**: ```c MppCtx ctx; MppParam param = MPP_CTX_DEC; // 必须明确设置为解码模式 mpp_init(ctx, param); ``` #### 2. 输入数据格式验证 - **AnnexB格式要求**:H.264解码器需要输入流包含起始码`0x00000001`。若输入为MP4格式(无起始码),需添加`h264_mp4toannexb`过滤器转换[^4]。 - **FFmpeg过滤器配置**: ```bash ffmpeg -i input.mp4 -codec:v copy -bsf:v h264_mp4toannexb output.h264 ``` #### 3. 硬件兼容性排查 - **GPU驱动检查**:类似MPICH的`gpu_init failed`问题[^3],需确认GPU驱动版本与MPP库兼容,通过`nvidia-smi`或`vulkaninfo`验证。 - **内存分配权限**:部分嵌入式平台(如RK芯片)需通过`dma-buf`分配内存,检查`/dev/mpp`设备权限。 #### 4. 错误日志深度分析 - **MPP错误码解析**:`error -1`通常表示参数不匹配或资源分配失败。通过`mpp_log`输出详细日志: ```c mpp_control(ctx, MPP_SET_OUTPUT_TIMEOUT, 1000); // 设置超时避免阻塞 ``` #### 5. wrapped_avframe问题处理 - **Filtergraph链路验证**:检查AVFrame传递链路是否完整,尤其注意`wrapped_avframe`需要显式设置像素格式(如`AV_PIX_FMT_DRM_PRIME`)。 - **数据流调试**: ```bash ffmpeg -v verbose -i input -f null - # 启用详细日志 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值