ZJOI 2012 T1 数列
题目大意:已知一个数列:
求它的第K项。
//=====================================================================================
直接按照题目给的条件DFS可拿30分左右,记忆化储存每个DFS到的Ai的数可以得到50分。再加高精度就可AC。
View Code
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<map> using namespace std; struct atp { int len; int a[15]; atp() { len=0; memset(a,0,sizeof(a)); } }a,one; struct Ha { int next; pair<atp,atp> data; }h[15000];int first[40000],tot; bool operator != (atp a,atp b) { if (a.len!=b.len) return true; for (int i=1;i<=a.len;i++) if (a.a[i]!=b.a[i]) return true; return false; } void insert(pair<atp,atp> a) { int x=a.first.len*a.first.a[a.first.len]%39997; tot++; h[tot].data=a; h[tot].next=first[x]; first[x]=tot; } pair<bool,atp> Find(atp a) { int x=a.len*a.a[a.len]%39997; if (first[x]==0) return pair<bool,atp>(false,a); x=first[x]; while (x!=0 && h[x].data.first!=a) x=h[x].next; if (x==0) return pair<bool,atp>(false,a); else return pair<bool,atp>(true,h[x].data.second); } void print(atp a) { printf("%d",a.a[a.len]); for (int i=a.len-1;i;i--) { if (a.a[i]<100000000)printf("0"); if (a.a[i]<10000000)printf("0"); if (a.a[i]<1000000)printf("0"); if (a.a[i]<100000)printf("0"); if (a.a[i]<10000)printf("0"); if (a.a[i]<1000)printf("0"); if (a.a[i]<100) printf("0"); if (a.a[i]<10) printf("0"); printf("%d",a.a[i]); } printf("\n"); } void init() { int l,temp=0; char s[110]; scanf("%s",s); l=strlen(s); a.len=l/9; temp=l%9; if (temp!=0) a.len++; else temp=9; for (int i=1;i<=temp;i++) a.a[a.len]=a.a[a.len]*10+s[i-1]-'0'; for (int i=1;i<a.len;i++) for (int j=temp+(i-1)*9+1;j<=temp+(i-1)*9+9;j++) a.a[a.len-i]=a.a[a.len-i]*10+s[j-1]-'0'; } atp Plus(atp a,atp b) { atp c; int len=max(a.len,b.len); for (int i=1;i<=len;i++) { c.a[i]+=a.a[i]+b.a[i]; c.a[i+1]+=c.a[i]/1000000000; c.a[i]%=1000000000; } if (c.a[len+1]!=0) len++; c.len=len; return c; } void Div(const atp &a,int b,atp &c,int &d) { int len; len=a.len; d=0; for(int i=len;i>=1;i--) { d=d*1000000000+a.a[i]; c.a[i]=d/b; d%=b; } while(len>1&&c.a[len]==0) len--; c.len=len; } atp dfs(atp a) { pair<bool,atp> p=Find(a); if (p.first) return p.second; atp c;int mod; Div(a,2,c,mod); if (mod==0) { p=Find(c); if (p.first) return p.second; else { atp t=dfs(c); insert(pair<atp,atp>(c,t)); return t; } } atp t1,t2; p=Find(c); if (p.first) t1=p.second; else { t1=dfs(c); insert(pair<atp,atp>(c,t1)); } p=Find(Plus(c,one)); if (p.first) t2=p.second; else { t2=dfs(Plus(c,one)); insert(pair<atp,atp>(Plus(c,one),t2)); } return Plus(t1,t2); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); one.len=1; insert(pair<atp,atp>(one,one)); one.a[1]=1; insert(pair<atp,atp>(one,one)); int Case; scanf("%d",&Case); atp ans; while (Case--) { memset(a.a,0,sizeof(a.a)); a.len=0; init(); ans=dfs(a); print(ans); } return 0; }
一开始高精度压4位,TLE,5位还是TLE...最后改到6位才AC...我这个常数控制的是有多烂啊啊...WJMZBMR单位压得都比我快... Orz 之...