• JZOJ 1421. 二叉树


    题目

    Description

      在一个无穷的满二叉树中,有以下几个特点:
      (1) 每个节点都有两个儿子——左儿子和右儿子;
      (2) 如果一个节点的编号为X,则它的左儿子编号为2X,右儿子为2X+1;
      (3) 根节点编号为1。
      现在从根结点开始走,每一步有三种选择:走到左儿子、走到右儿子和停在原地。
      用字母“L”表示走到左儿子,“R”表示走到右儿子,“P”表示停在原地,用这三个字母组成的字符串表示一个明确的行走路线。
    一个明确的行走路线的价值为最终到达节点的编号,例如LR的价值为5,而RPP的价值为3。
      我们用字符“L”、“R”、“P”和“*”组成的字符串表示一组行走路线,其中“*”可以是“L”、“R”、“P”中的任意一种,所有跟这个行走路线匹配的字符串都认为是可行的。
      例如L*R包含LLR、LRR和LPR。而**包含LL、LR、LP、RL、RR、RP、PL、PR和PP这9种路线。
      一组行走路线的价值等于所有匹配该模式的路线的价值之和。请你编程计算给定路线的价值。
     

    Input

      输入一个字符串表示一组行走路线,里面只含有“L”、“R”、“P”和“*”四种字符,长度不会超过10000。

    Output

      输出该路线的价值。
     

    Sample Input

    输入1:
    P*P
    
    输入2:
    L*R
    
    输入3:
    **
    
    输入4:
    LLLLLRRRRRLLLLLRRRRRLLLLLRRRRRLLLLL

    Sample Output

    输出1:
    6
    
    输出2:
    25
    
    输出3:
    33
    
    输出4:
    35400942560
     

    Data Constraint

     
     

    Hint

    【数据范围】
      30%的数据满足路线中不含“*”;
      50%的数据满足最多只有3个“*”。

    Source / Author: COCI2008

    分析

    •  
       假设经过k个*号,构造出了3^k个不同的数。
      下一位是L:每个数同时*2,即总和*2
      下一位是R:每个数同时*2+1,即总和*2+1*数的个数(3^k)
      下一位是*:从3^k个数变成3^(k+1)个数
      其中3^k个数没有变化,总和*1
      另外3^k个数加上了一个L,总和*2
      还有3^k个数加上了一个R,每个数*2+1,即总和*2+1*数的个数(3^k)
      综上,总和*5+3^k。
      加个押位高精度就没了。

     

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 const int N=1e4+10,mo=1e8;
     6 char s[N];
     7 int f[N],p[N];
     8 long long ans=0;
     9 void mul(int x)
    10 {
    11     for (int i=f[0];i>=1;i--) f[i]*=x,f[i+1]+=f[i]/mo,f[i]%=mo;
    12     if (f[f[0]+1]) f[0]++;
    13 } 
    14 void tmp()
    15 {
    16     for (int i=p[0];i>=1;i--) p[i]*=3,p[i+1]+=p[i]/mo,p[i]%=mo;
    17     if (p[p[0]+1]) p[0]++;
    18 }
    19 void add()
    20 {
    21     for (int i=1;i<=max(p[0],f[0]);i++) f[i]+=p[i],f[i+1]+=f[i]/mo,f[i]%=mo;
    22     if (f[f[0]+1]) f[0]++;
    23 }
    24 int main ()
    25 {
    26     int len;
    27     cin>>s+1;
    28     len=strlen(s+1);
    29     p[0]=p[1]=f[0]=f[1]=1;
    30     for (int i=1;i<=len;i++)
    31     {
    32         if (s[i]=='L') mul(2);
    33         else if (s[i]=='R') mul(2),add();
    34         else if (s[i]=='*') mul(5),add(),tmp(); 
    35     }
    36     cout<<f[f[0]];
    37     for (int i=f[0]-1;i>=1;i--) printf("%08d",f[i]);
    38 }
    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    Java开发笔记(四十二)日历工具的常见应用
    Java开发笔记(四十一)日历工具Calendar
    Java开发笔记(四十)日期与字符串的互相转换
    Java开发笔记(三十九)日期工具Date
    Java开发笔记(三十八)利用正则表达式校验字符串
    Java开发笔记(三十七)利用正则串分割字符串
    Java开发笔记(三十六)字符串的常用方法
    Java开发笔记(三十五)字符串格式化
    Git 工作流程
    如果你恨一个程序员,忽悠他去做iOS开发
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/11100026.html
Copyright © 2020-2023  润新知