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 }