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是第几轮构造出来的我裂开来

原文地址:https://www.cnblogs.com/randomaddress/p/11600911.html