1604. 电压放大器(amp)
题目描述
西西需要把输入的电压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,12+1=3,然后经过1,32-1=5。满足要求
思路:
根据题意,初值为1,所以第一个放大器要选2x+1。
接下来因为2x为偶数,所以-1和+1为奇数,故偶数倍是不可能的。
然后把前几种可能生成的倍数情况打表,不难发现所有的奇数都可以生成。
n一定是由n/2,n/2+1中的一个数通过放大器得来。具体通过哪个放大器,可找一下规律。如果n/2是个偶数,就选n/2+1通过2x-1得来,反之由n/2通过2x+1得来。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e9;
long long n,a[50],tot;
int main()
{
fre(amp);
scanf("%lld",&n);
if(n%2==0) printf("No solution\n");
while(n!=1)
{
long long temp=n/2;
if(temp%2==1) a[++tot]=2,n=temp;
else a[++tot]=1,n=temp+1;
}
printf("%lld\n",tot);
for(long long i=tot;i>=1;i--) printf("%lld ",a[i]);
return 0;
}