2019/9/27 题解:【T100043】 2019/9/27 Day2 T1 无穷序列

    题解:【T100043】  无穷序列

  题目:

  

  输入输出格式:

         

  样例:

  

  数据范围:

  

  思路:

                                        k==6时的数列

  此数列构造方式是第k轮构造在第k-1轮的基础上,将数列复制并添加到原数列后,再添加上数字k。

                                  

                                示意图(比例出了一点问题但不要在意)

  由此我们不难发现:

  1. 原数列第k轮复制后某一待求数a[x]与原数列a[i]对应并且相等,即 x=i+(last[k-1] - 0)(原数列长度) 且 a[i]=a[x] 。

  2. 只有在第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 }

  //有大佬(@全机房最该跳下去的人)是用纯数学方法得到公式用log计算的但我没有想到(不会),大佬代码日后可能会po上来

  //亲测不加unsigned 80分(坑死我了)

  //2019/9/27 23:02 我突然想到log是用来直接求x是第几轮构造出来的我裂开来

猜你喜欢

转载自www.cnblogs.com/randomaddress/p/11600911.html