• 【市选模拟题】电压放大器


    题目描述
    西西需要把输入的电压1伏通过一系列电压放大器放大成原来的N倍,然后输出。
    西西现在手上有两种放大器:
    第一种能够把X伏的电压放大成2X-1伏
    第二种能够把X伏的电压放大成2X+1伏
    放大器是串联(即按顺序放在一条线路上)的。
    现在西西手上有用不完的放大器,他希望能组出一个电路,使用数量最少的放大器,使得电压被放大了刚好N倍。

    输入
    一行一个正整数N(1<=N<=2*10^9)

    输出
    如果无法组成电路则输出一行No solution
    否则输出两行,第一行一个整数表示最少的放大器个数K,第二行K个用空格隔开的1或2,表示放大器序列。1表示第一种,2表示第二种,其中左边为输入端。如果有多解输出任意一组。

    样例输入
    5

    样例输出
    2
    2 1

    数据范围限制
    20%的数据中 N<=1000
    50%的数据中,N<=1000000
    100%的数据如题。

    提示
    先经过放大器2,1 * 2+1=3,然后经过1,3 * 2-1=5。满足要求

    思路:

    铺垫:

    想都不想多的,我们直接开始暴力枚举,先想log2(109)<30,暴力枚举完全部也只用230,更别说只找到一个正解就可以,其实真实时间复杂度为O(log(n))左右。
    我们可以从奇偶性分析:
    1.奇数×2+1=奇数
    2.偶数×2+1=奇数
    3.奇数×2-1=奇数
    4.偶数×2-1=奇数

    正解:

    我用的是倒推法,剪枝条件就用以上铺垫的奇偶性分析,当参数为偶是退出,直到找到正解为止。
    优先枚举第二种情况才可以保证使用最少的放大器(重点)
    实现

    void dfs(int o){
    	if(o%2==0) return ;//剪枝条件
    	if(bj==1) return ;//找到一个后就不找了
    	if(o==1){//找到正解
    		bj=1;
    		printf("%d
    ",a[0]);
    		for(int i=a[0];i>=1;i--){
    			printf("%d ",a[i]);
    		}
    		return ;
    	}
    	a[0]++;
    	a[a[0]]=2;
    	dfs((o-1)/2);//优先枚举第二种情况才可以保证使用最少的放大器(重点)
    	a[a[0]]=1;
    	dfs((o+1)/2);//枚举第一种放大器
    	a[a[0]]=0;
    	a[0]--; 
    }
    
  • 相关阅读:
    2017.12.16 扫雷小游戏未完成
    2017.12.15 计算机算法分析与设计 枚举
    2017.12.14 Java实现-----图书管理系统
    2017.12.13 Java中是怎样通过类名,创建一个这个类的数组
    2017.12.12 基于类的面向对象和基于原型的面向对象方式比较
    2017.12.11 String 类中常用的方法
    2017.12.10 Java写一个杨辉三角(二维数组的应用)
    2017.12.9 Java中的排序---冒泡排序、快速排序、选择排序
    spring boot compiler 版本实践
    spring boot 首次请求Controller慢
  • 原文地址:https://www.cnblogs.com/2020-zhy-jzoj/p/13159882.html
Copyright © 2020-2023  润新知