• [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 }
    View Code
     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 }
    View Code
  • 相关阅读:
    sqlserver建立临时表
    动态引用WebService
    技术的力量:30分钟的动画片和《彗星撞地球》超炫的动画 仅64K
    sqlserver2005新功能函数
    使用面向对象的、完整的单点登录功能
    asp.net上传功能(单文件,多文件,自定义生成缩略图,水印)
    C#对字符和文件的加密解密类
    JavaScript中setInterval函数应用常见问题之一(第一个参数不加引号与加引号的区别)
    JavaScript表格隔行换色悬停高亮
    Javascript模拟c#中arraylist操作(学习分享)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16168319.html
Copyright © 2020-2023  润新知