(纪中)1604. 【市选模拟题】电压放大器【数学】

119 篇文章 0 订阅

(File IO): input:amp.in output:amp.out
时间限制: 1000 ms 空间限制: 128000 KB 具体限制 Special Judge


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


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

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


样例输入
5

样例输出
2
2 1


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


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


解题思路
题目大意:给你一个 1 1 1,让你经过多次操作(分两种: 2 x + 1 2x+1 2x+1 2 x − 1 2x-1 2x1)变为 n n n这个数,求最少要多少步,并输出操作序号。

主要思路(分两种):
(1)爆搜无极限 本蒟蒻当时就只打了暴搜QWQ, 60 60 60 ,唉,可惜时间复杂度不允许啊……

(2)我们可以从奇偶性分析,一开始的 1 1 1为奇数开始模拟一下所有步骤:
1. 1. 1.奇数 × 2 + 1 = ×2+1= ×2+1=奇数
2. 2. 2.偶数 × 2 + 1 = ×2+1= ×2+1=奇数
3. 3. 3.奇数 × 2 − 1 = ×2-1= ×21=奇数
4. 4. 4.偶数 × 2 − 1 = ×2-1= ×21=奇数
那这么看来,这个变化中的序列肯定是个奇数序列了。 S o So So,只要n是偶数输出 N o No No s o l u t i o n solution solution
我们开始分析一下样例: 5 5 5
肯定是先第二种再第一种,这时我们反着推: ( 5 + 1 ) / 2 = 3 , ( 3 − 1 ) / 2 = 1 (5+1)/2=3,(3-1)/2=1 5+1/2=3,(31)/2=1
我们这时可以思考到:为什么 5 5 5只能 + 1 +1 +1 / 2 /2 /2,而 3 3 3可以 − 1 -1 1 / 2 /2 /2呢?我们可以先列一个奇数表
表: 1 , 3 , 5 , 7 , 9 , 11 , 13 , 15 , 17 , 19 … … 1 ,3 ,5 ,7 ,9 ,11 ,13 ,15 ,17 ,19…… 1,3,5,7,9,11,13,15,17,19
标记 + 1 , − 1 , + 1 , − 1 , + 1 , − 1 , + 1 , − 1 , + 1 , − 1 … … +1,-1,+1,-1,+1,-1, +1 ,-1, +1, -1…… +1,1,+1,1,+1,1,+1,1,+1,1
我们可以发现 + 1 , − 1 +1,-1 +11好像就是按他们在这个奇数数列中位置而变。那就是求项数 % 2== 什么了。
那这就好办了每次去判断现在他的项数为偶数就 ( x − 1 ) / 2 (x-1)/2 x1/2否则就 ( x + 1 ) / 2 (x+1)/2 x+1/2


代码·

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<map>
using namespace std;
int n,x,t,ans[105];
int main()
{
	freopen("amp.in","r",stdin);
    freopen("amp.out","w",stdout);
    scanf("%d",&n);
    if(n%2==0)
		printf("No solution");
	else
	{
		x=n,t=0;
		while(x!=1)
		{
			if(((x-1)/2+1)%2==1)
				x=(x+1)/2,ans[++t]=1;
			else
				x=(x-1)/2,ans[++t]=2;
		}
			
		printf("%d\n",t);
		for(int i=t;i>=1;--i)
			printf("%d ",ans[i]);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值