(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
2X−1伏
第二种能够把
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<=2∗109)
输出
如果无法组成电路则输出一行
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
1∗2+1=3,然后经过
1
1
1,
3
∗
2
−
1
=
5
3*2-1=5
3∗2−1=5。满足要求
解题思路
题目大意:给你一个
1
1
1,让你经过多次操作(分两种:
2
x
+
1
2x+1
2x+1和
2
x
−
1
2x-1
2x−1)变为
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=
×2−1=奇数
4.
4.
4.偶数
×
2
−
1
=
×2-1=
×2−1=奇数
那这么看来,这个变化中的序列肯定是个奇数序列了。
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,(3−1)/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
+1,−1好像就是按他们在这个奇数数列中位置而变。那就是求项数 % 2== 什么了。
那这就好办了每次去判断现在他的项数为偶数就
(
x
−
1
)
/
2
(x-1)/2
(x−1)/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]);
}
}