zoukankan      html  css  js  c++  java
  • UVA-12333 Revenge of Fibonacci

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3755

    题目大意:

    意思不难理解,就是找到以某个字符串为前缀的最小的斐波拉契数列,并输出是第几个斐波拉契数。找不到就输出-1;

    思路:大数加法,字典树。

    ps:通过这道题接触到了大数加法。(虽然之前在刘汝佳的那本算法书里看到过阶乘的,但当时匆匆略过了)

    该题是多组输入,我们就对斐波拉契数列预处理,将1——100000的斐波拉契数列找出来。

    将它们存入字典树。长度超过40的就只压入长度为41的前缀。

    然后在每个节点存入以当前前缀为最小的斐波拉契数的序号。

    ps:斐波拉契数列不能多存了一个!只要你超过了100000个就wa,它卡了这个点;

    之所以不全部存入是为了节省空间。不然会RE。

    然后代码应该就能AC了。

    ps:本人代码跑了8330ms,感觉都要tle了。看到他们都是几百ms就ac了,不造怎么写的。时间问题就没有去看。

     ps:知道在哪时间耗了那么久了,就是大数加法的那里最好判断一下是否数据超过了49位,是的话我们就舍去后面的位数。因为它前缀查询是不超过40位,那么我们就只需考虑前40位,但是会有误差,所以我们为了保险起见,我们选择49位。这样就避免误差了。现在附上第二份代码,耗时770ms,1s也能AC了

    ps:不知道为什么我今天用自己的代码提交出现TLE,但是过段时间重复提交几次后又AC了,可能因为是服务器的问题吧。。。

    代码如下

     1 #include<iostream>
     2 #include<stdio.h>
     3 using namespace std;
     4 string fib(string s1,string s2)
     5 {
     6     if(s1.length()<s2.length())
     7     {
     8         string temp=s1;
     9         s1=s2;
    10         s2=temp;
    11     }
    12     int i,j;
    13     for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
    14     {
    15         s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));
    16         if(s1[i]-'0'>=10)
    17         {
    18             s1[i]=char((s1[i]-'0')%10+'0');
    19             if(i) s1[i-1]++;
    20             else s1='1'+s1;
    21         }
    22     }
    23     return s1;
    24 }
    25 string a[100002];
    26 int cnt=1;
    27 int sum[10000050][11];
    28 int num[10000050];
    29 void add(string s,int number)
    30 {
    31     int root=0;
    32     for(int i=0;i<s.length()&&i<42;i++)
    33     {
    34         int xx=s[i]-'0';
    35         if(!sum[root][xx])
    36         {
    37             sum[root][xx]=cnt++;
    38             num[sum[root][xx]]=number;//存入最小的前缀,因为数列本身就是从小到大排,存入序号就ok
    39         }
    40         root=sum[root][xx];
    41     }
    42 }
    43 int Find(string s)
    44 {
    45     int root=0;
    46     for(int i=0;i<s.length();i++)
    47     {
    48         int xx=s[i]-'0';
    49         root=sum[root][xx];
    50         if(root==0)
    51             return 0;
    52     }
    53     return num[root];
    54 }
    55 int main()
    56 {
    57     a[1]="1";
    58     a[2]="1";
    59     add(a[1],1);
    60     add(a[2],2);
    61     for(int i=3;i<=100000;i++)//预处理
    62     {
    63         a[i]=fib(a[i-1],a[i-2]);
    64         add(a[i],i);
    65     }
    66     int T;
    67     while(cin>>T)
    68     {
    69         int t=0;
    70         string st;
    71         while(T--)
    72         {
    73             t++;
    74             cin>>st;
    75             int tmp=Find(st);
    76             if(tmp){
    77                 cout<<"Case #"<<t<<": "<<tmp-1<<endl;//因为题目从0开始算,所以减一
    78             }else{
    79                 cout<<"Case #"<<t<<": "<<-1<<endl;
    80             }
    81         }
    82     }
    83     return 0;
    84 }

    优化后的代码:

      1 #include<iostream>
      2 #include<stdio.h>
      3 using namespace std;
      4 string fib(string s1,string s2)
      5 {
      6     if(s1.length()<s2.length())
      7     {
      8         string temp=s1;
      9         s1=s2;
     10         s2=temp;
     11     }
     12     int i,j;
     13     if(s2.length()>49)
     14     {
     15         for(i=49,j=s2.length()+49-s1.length();i>=0;i--,j--)
     16         {
     17             s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));
     18             if(s1[i]-'0'>=10)
     19             {
     20                 s1[i]=char((s1[i]-'0')%10+'0');
     21                 if(i) s1[i-1]++;
     22                 else s1='1'+s1;
     23             }
     24         }
     25     }
     26     else
     27     {
     28         for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
     29         {
     30             s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));
     31             if(s1[i]-'0'>=10)
     32             {
     33                 s1[i]=char((s1[i]-'0')%10+'0');
     34                 if(i) s1[i-1]++;
     35                 else s1='1'+s1;
     36             }
     37         }
     38     }
     39     return s1;
     40 }
     41 string a[100002];
     42 int cnt=1;
     43 int sum[10000050][11];
     44 int num[10000050];
     45 void add(string s,int number)
     46 {
     47     int root=0;
     48     for(int i=0;i<s.length()&&i<42;i++)
     49     {
     50         int xx=s[i]-'0';
     51         if(!sum[root][xx])
     52         {
     53             sum[root][xx]=cnt++;
     54             num[sum[root][xx]]=number;
     55         }
     56         root=sum[root][xx];
     57     }
     58 }
     59 int Find(string s)
     60 {
     61     int root=0;
     62     for(int i=0;i<s.length();i++)
     63     {
     64         int xx=s[i]-'0';
     65         root=sum[root][xx];
     66         if(root==0)
     67             return 0;
     68     }
     69     return num[root];
     70 }
     71 int main()
     72 {
     73     a[1]="1";
     74     a[2]="1";
     75     add(a[1],1);
     76     add(a[2],2);
     77     for(int i=3;i<=100000;i++)
     78     {
     79         a[i]=fib(a[i-1],a[i-2]);
     80         add(a[i],i);
     81     }
     82     int T;
     83     while(cin>>T)
     84     {
     85         int t=0;
     86         string st;
     87         while(T--)
     88         {
     89             t++;
     90             cin>>st;
     91             int tmp=Find(st);
     92             if(tmp){
     93                 cout<<"Case #"<<t<<": "<<tmp-1<<endl;
     94             }else{
     95                 cout<<"Case #"<<t<<": "<<-1<<endl;
     96             }
     97         }
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    HDU-2544-最短路(floyd)
    HDU-1009-肥鼠交易
    BZOJ-3029: 守卫者的挑战 (期望DP)
    2017年10月23日23:58:04
    BZOJ-2456: mode (神题)
    BZOJ-4542: [Hnoi2016]大数 (莫队算法)
    BZOJ-2120: 数颜色 (带修改莫队)
    BZOJ-2654: tree (kruskal)
    BZOJ-1040: [ZJOI2008]骑士 (树形DP)
    BZOJ-3505: [Cqoi2014]数三角形 (容斥原理+排列组合)
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/7248071.html
Copyright © 2011-2022 走看看