hdu4099

  要想通这个题目应该很容易,由于斐波纳契数在近100项之后很大,早就超出long long了。而输入最长的序列才40个数字,所以大约保留前50位,前40位是没有误差的!!!其实,想想我们判断double数字相等时fabs(a-b)<1e-10来忽略double数字由于加法带来的误差,道理是一样的,甚至C++默认的还是1e-5。而保险起见,我的方法中保留了100位。当然这个保留50位的数字加法,也只能模拟一遍,因为要计算10^5项。

  然而测试样例有50000组,所以我们先要对输入的字符串做一个字典树!虽然我没学过也没听过,后来AC了队友跟我说这个叫字典树,写个博客纪念一下。

  YY一下,我弹了近8次,前3次因为没有建字典树超时,后5次竟然是因为第0项也是计入的,斐波那契序列为1,1,2,3,5,8……。而我竟然认为第一个1不算的。擦擦,其实样例都没过,我一直以为过了,然后还找不到思路错哪了。我是有多眼瞎啊!!!今年还有最后一次机会,希望比赛拿点成绩,千万别再坑这里了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxlen=100000;
 6 const int maxn=maxlen+1010;
 7 char target[60];
 8 int active_id,active_idx;
 9 void ccplus(char *&ch,int &cl,char *&sh,int &sl){
10     if(cl < sl) ch--,cl++, ch[0]='0';
11     char carry=0; int idx=cl;
12     while(idx--){
13         ch[idx] += sh[idx]+carry-'0';
14         if(ch[idx] > '9') ch[idx]-=10, carry=1;
15         else carry=0;
16     }
17     if(carry) ch--,cl++, ch[0]='1';
18     if(cl > 100) cl--, sl--;
19     ch[cl]='\0';
20     //if(active_idx <= 25) printf("active_idx = %d, ch = %s, cl = %d\n",active_idx,ch,cl);
21     swap(ch,sh); swap(cl,sl);
22 }
23 char f1[maxn],f2[maxn];
24 char *ch,*sh;
25 int cl,sl;
26 const int maxt=50010;
27 struct tree{
28     int id;
29     int next[10];
30     void init(int i=-1){ id=i; for(int j=0;j<10;j++) next[j]=-1; }
31 }tr[maxt*45];
32 int tcnt=1;
33 int value[maxt],idnext[maxt];
34 void make_tree(int idx,char *tt){
35     //printf("idx = %d, tt[1] = %s\n",idx,tt+1); //char cc; cin>>cc;
36     if(tt[1]=='\0'){
37         if(tr[idx].id <= 0) tr[idx].id = active_id;
38         else {
39             int t = tr[idx].id;
40             while(idnext[t] > 0) t = idnext[t];
41             idnext[t] = active_id;
42         }
43         return;
44     }
45     int ne=tt[1]-'0';
46     //if(ne < 0)  cout<<"fuck ne = "<<ne<<endl;
47     if(tr[idx].next[ne] <= 0)
48         tr[idx].next[ne]=tcnt, tr[tcnt].init(), tcnt++;
49     make_tree(tr[idx].next[ne],tt+1);
50 }
51 void search_tree(int idx,char *tt){
52     int id=tr[idx].id;
53     if(id > 0 && value[id] < 0) {
54         value[id]=active_idx;
55         while(idnext[id] > 0) id=idnext[id], value[id]=active_idx;
56     }
57     int ne=tt[1]-'0';
58     if(tt[1] == '\0' || tr[idx].next[ne] <= 0) return;
59     search_tree(tr[idx].next[ne],tt+1);
60 }
61 int main()
62 {
63     int cases; cin>>cases;
64     memset(idnext,-1,sizeof(idnext));
65     memset(value,-1,sizeof(value));
66     tr[0].init(0);
67     for(int cas=1;cas<=cases;cas++) {
68             scanf("%s",target+1);
69             active_id = cas;
70             make_tree(0,target);
71             //cout<<"case "<<cas<<" is over!"<<endl;
72     }
73     ch=&f1[maxn-60],sh=&f2[maxn-60];
74     ch[0]='1', ch[1]='\0';
75     sh[0]='2', sh[1]='\0';
76     cl=sl=1;
77     active_idx=0; search_tree(0,ch-1);
78     active_idx=1; search_tree(0,ch-1);
79     active_idx=2; search_tree(0,sh-1);
80     active_idx=3;
81     while(active_idx < maxlen)
82         ccplus(ch,cl,sh,sl), search_tree(0,sh-1), active_idx++;
83     for(int cas=1;cas<=cases;cas++)
84         printf("Case #%d: %d\n",cas,value[cas]);
85     return 0;
86 }
View Code

 

  

posted on 2013-09-10 21:26  男神发量  阅读(267)  评论(0编辑  收藏  举报