[uoj728]坏掉的设备2
构造$\{t_{i}\}=10101\cdots $,此时将$10$分别看作$\pm 1$,则其前缀和$\in \{0,1\}$
此时,将两者"乱序归并"后,其对$\{s_{i}\}$前缀和的影响不大,进而有以下构造——
记$a_{i}$为$A$二进制下第$i$位,$\forall i\in [1,60]$依次在$\{s_{i}\}$末尾加入$2+[a_{i}\ne a_{i-1}]$个$a_{i}$(定义$a_{0}=1$)
乱序合并后,维护$s$表示$\{u_{i}\}$的前缀和,每当$|s|\ge 2$则得到下一位(根据$s$的符号)并清空$s=0$
关于上述做法的正确性,证明如下——
归纳证明前$k-1$位正确且第$k$位至少在混合到$\{s_{i}\}$中第1个$a_{k}$后得到
注意到忽略$\{t_{i}\}$时,$1$恰会在最后一个$a_{k}$上得到$,0$恰会在倒数第2个$a_{k}$上得到
在此基础上,$\{t_{i}\}$至多使前者向前一个/后者向后一个,均在$a_{k}$上,进而第$k$位也正确
若在最后一个$a_{k}$上得到,显然仅通过$\{t_{i}\}$无法达到$\pm 2$,因此必然用到$a_{k+1}$
若在倒数第2个$a_{k}$上得到,注意到此时$a_{k}$和$\{t_{i}\}$的下一位相同,同样需要用到$a_{k+1}$
事实上,上述做法本质上即能够确定满足以下条件的$\{s_{i}\}$
条件:每一个极长$01$段的长度为$\ge 3$的奇数(以$1$为开头则该段长度为偶数)
进一步的,考虑以下两个优化——
优化1:在$\{s_{i}\}$末尾不断加入一个与原来末尾不同的字符
结合前面的分析,这样不会使得$s$达到$\pm 2$,进而可以确定额外增加的长度
优化2:在$\{s_{i}\}$开头增加一个1,并将所有$\{s_{i}\}$和$\{t_{i}\}$中的$01$翻转
此时,$\{u_{i}\}$中的第1个字符变为标识符,并对之后的字符做同样的处理
打表可得上述形式且长度$\le 140$的$\{s_{i}\}$个数$\ge 10^{18}$,将这些$\{s_{i}\}$编号即可
1 #include<bits/stdc++.h> 2 #include "Anna.h" 3 using namespace std; 4 #define N 200 5 #define ll long long 6 #define vi vector<int> 7 int n,len;ll sum,f1[N],f2[N];vi s,t; 8 int Declare(){ 9 n=140,f1[0]=f2[0]=1,sum=f2[1]=0; 10 for(int i=1;i<n;i++){ 11 f1[i]=0; 12 for(int j=3;j<=i;j+=2)f1[i]+=f1[i-j]; 13 } 14 for(int i=2;i<n;i++)f2[i]=f1[i]+f2[i-2]; 15 for(int i=1;i<n;i++)sum+=(n-i)*f2[i]; 16 return n; 17 } 18 void add(int k,int p){ 19 for(int i=1;i<=k;i++)s.push_back(p); 20 } 21 pair<vi,vi> Anna(ll A){ 22 s.clear(),t.clear(); 23 bool flag=0; 24 if (sum<A)A-=sum,flag=1; 25 for(int i=1;i<n;i++){ 26 if ((n-i)*f2[i]<A)A-=(n-i)*f2[i]; 27 else{ 28 for(int j=0;j<n-i;j++) 29 if (f2[i]<A)A-=f2[i]; 30 else{ 31 len=i+j+1,s.push_back(1); 32 while (i){ 33 if (f1[i]<A)A-=f1[i],i-=2,add(2,1); 34 else{ 35 int p=0; 36 while (i){ 37 i-=3,add(3,p); 38 while (f1[i]<A)A-=f1[i],i-=2,add(2,p); 39 p^=1; 40 } 41 } 42 } 43 for(int k=1;k<=j;k++)s.push_back(s.back()^1); 44 for(int k=1;k<=len;k++)t.push_back(k&1); 45 if (flag){ 46 for(int k=0;k<len;k++)s[k]^=1,t[k]^=1; 47 } 48 return make_pair(s,t); 49 } 50 } 51 } 52 }
1 #include<bits/stdc++.h> 2 #include "Bruno.h" 3 using namespace std; 4 #define N 200 5 #define ll long long 6 #define vi vector<int> 7 int n,len;ll sum,ans,f1[N],f2[N];vi v; 8 void init(){ 9 n=140,f1[0]=f2[0]=1,sum=f2[1]=0; 10 for(int i=1;i<n;i++){ 11 f1[i]=0; 12 for(int j=3;j<=i;j+=2)f1[i]+=f1[i-j]; 13 } 14 for(int i=2;i<n;i++)f2[i]=f1[i]+f2[i-2]; 15 for(int i=1;i<n;i++)sum+=(n-i)*f2[i]; 16 } 17 ll Bruno(vi u){ 18 init(); 19 len=(u.size()>>1),ans=1,v.clear(); 20 if (!u[0]){ 21 ans+=sum; 22 for(int i=0;i<u.size();i++)u[i]^=1; 23 } 24 int s=0;u.erase(u.begin()); 25 for(int i:u){ 26 s+=(i ? 1 : -1); 27 if (abs(s)>=2)v.push_back(s==2),s=0; 28 } 29 int leni=2+(v[0]!=1); 30 for(int i=1;i<v.size();i++)leni+=2+(v[i]!=v[i-1]); 31 for(int i=1;i<leni;i++)ans+=(n-i)*f2[i]; 32 ans+=(len-leni-1)*f2[leni]; 33 for(int i=0,j=0;i<v.size();i=j){ 34 if ((i)||(!v[i]))leni-=3,j++; 35 while ((j<v.size())&&(v[i]==v[j]))ans+=f1[leni],leni-=2,j++; 36 } 37 return ans; 38 }