2019/9/27 题解:【T100043】 2019/9/27 Day2 T1 无穷序列
题解:【T100043】 无穷序列
题目:
输入输出格式:
样例:
数据范围:
思路:
k==6时的数列
此数列构造方式是第k轮构造在第k-1轮的基础上,将数列复制并添加到原数列后,再添加上数字k。
示意图(比例出了一点问题但不要在意)
由此我们不难发现:
-
原数列第k轮复制后某一待求数a[x]与原数列a[i]对应并且相等,即 x=i+(last[k-1] - 0)(原数列长度) 且 a[i]=a[x] 。
-
只有在第k轮构造时,数字k才会第一次出现。即当 x=last[ k ](第k轮最后一个数位置) 时有a[x]= k 。
综上可通过将待求数a[x]向前逆推得到a[i],当a[i]为第一次出现时有a[x]=a[i]=last[k]=k。
代码:
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #define mod 998244353//记得不用模
5 using namespace std;
6 unsigned long long last[65];
7 unsigned long long num[65];//没用
8 unsigned long long x;//记得unsigned,10^19约等于2^64,最多构造64轮,long long会爆
9 int t;
10 int main()
11 {
12 //freopen("endless.in","r",stdin);
13 //freopen("endless.out","w",stdout);
14 cin>>t;
15 unsigned long long tmp=0;
16 for(int i=1;i<=64;i++)//最多有64轮
17 {tmp=tmp*2+1;last[i]=tmp;}//预处理每轮构造时最后一个数(新增加的)位置
18 while(t--)
19 {
20 cin>>x;
21 int tk;//第x个数为第tk轮构造出来的
22 for(int k=1;k;k++)
23 {
24 if(last[k]>=x)
25 {tk=k;break;}
26 }
27 for(int j=tk+1;j>=1;j--)//加不加1无所谓
28 {if(x>last[j]){x=x-last[j];/*递推出上一个位置i*/}if(x==last[j]){cout<<j<<endl;/*如果为新出现数则a[x]=j*/}}
29 }
30 return 0;
31 }