HDU/杭电2013多校第三场解题报告
今天悲剧了,各种被虐啊,还是太年轻了
Crime
这道题目给的时间好长,第一次就想到了暴力,结果华丽丽的TLE了。
后来找了一下,发现前24个是1, 2, 6, 12, 72, 72, 864, 1728, 13824, 22032, 555264, 476928, 17625600, 29599488, 321115392, 805146624, 46097049600, 36481536000, 2754120268800, 3661604352000, 83905105305600, 192859121664000, 20092043520000000, 15074060547686400。这样我们就需要找到递推的式子。可是怎么也推不出。请路过的大神指教。。。
JZPTREE
这道题目是我看的,题目挺好懂的,就是数据量太大。不知道怎么写,最后想尽办法也只能压缩到十二亿。果断不行,怎么优化呢?
Jinkeloid
深坑....
The Unsolvable Problem
这道题目是过的最多的了题目了。就是that a + b = n and [a, b] is as large as possible. [a, b] denote the least common multiplier of a, b.这样的话就直接求就行了。是偶数的话变成前后值,否则前后判:#include <iostream> #include <cstdio> #include <string> #include <string.h> #include <map> #include <vector> #include <cstdlib> #include <algorithm> #include <cmath> #include <queue> #include <set> #include <stack> using namespace std; int main() { int t; __int64 n; cin>>t; while(t--) { cin>>n; if(n==2) { cout<<1<<endl; continue; } if(n%2==1) { cout<<(n/2)*(n/2+1)<<endl; } else { if((n/2)%2==0) { cout<<(n/2-1)*(n/2+1)<<endl; } else { cout<<(n/2-2)*(n/2+2)<<endl; } } } return 0; }
Pieces
这是经次于上一道出的最多的题了。就是把一个字符串变空。用的方法就是每次去一个回文串,直到取空。唯一的要求就是最后操作的次数要最小。这道题目需要考虑每次操作之后对后续的影响,不能直接求最长的回文串,可能后面就会因为这次操作而增加了操作次数;
Burning
一道几何题目,特判,精度...Sad Love Story
这道题目T到死了。先用最近点对的方法求了,TTT。后来有交KD-tree的,结果也T了,这不科学啊,20S额。这:
#include <iostream> #include <cstdio> #include <string> #include <string.h> #include <map> #include <vector> #include <cstdlib> #include <cmath> #include <algorithm> #include <cmath> #include <queue> #include <set> #include <stack> using namespace std; // 分治算法求最近点对 struct point { __int64 x , y; } p[500005],pp[500005]; __int64 a[500005]; //保存筛选的坐标点的索引 __int64 cmpx(const point &a , const point &b) { return a.x < b.x; } __int64 cmpy(__int64 a , __int64 b) //这里用的是下标索引 { return p[a].y < p[b].y; } inline __int64 dis(point &a , point &b) { return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); } inline __int64 min(__int64 a , __int64 b) { return a < b ? a : b; } __int64 closest(__int64 low , __int64 high) { if(low + 1 == high) return dis(p[low] , p[high]); if(low + 2 == high) return min(dis(p[low] , p[high]) , min( dis(p[low] , p[low+1]) , dis(p[low+1] , p[high]) )); __int64 mid = (low + high)>>1;//求中点 __int64 ans = min( closest(low , mid) , closest(mid + 1 , high) ); //分治法进行递归求解 __int64 i , j , cnt = 0; for(i = low ; i <= high ; ++i) //把x坐标在p[mid].x-ans~p[mid].x+ans范围内的点取出来 { if(p[i].x >= p[mid].x - ans && p[i].x <= p[mid].x + ans) a[cnt++] = i; //保存的是下标索引 } sort(a,a + cnt,cmpy); //按y坐标进行升序排序 for(i = 0 ; i < cnt ; ++i) { for(j = i+1 ; j < cnt ; ++j) { if(p[a[j]].y - p[a[i]].y >= ans) //注意下标索引 break; ans = min(ans , dis(p[a[i]] , p[a[j]])); } } return ans; } int main() { __int64 t; scanf("%I64d", &t); __int64 n, ax, bx,cx,ay,by,cy; __int64 ans = 0; while(t--) { ans = 0; scanf("%I64d", &n); scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &ax,&bx,&cx,&ay,&by,&cy); for(int i = 0; i < n; ++i) { if(i==0) { pp[i].x = (0*ax+bx)%cx; pp[i].y = (0*ay+by)%cy; } else { pp[i].x = (pp[i-1].x*ax+bx)%cx; pp[i].y = (pp[i-1].y*ay+by)%cy; int tp = i; for(int kp = 0; kp <= i; ++kp) { p[kp].x = pp[kp].x; p[kp].y = pp[kp].y; } sort(p , p+tp+1 , cmpx); ans += closest(0 , tp); } } printf("%I64d\n", ans); } return 0; }
KD-tree
#include <iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define D 2 #define N 500010 const int inf=1000000001; const long long Inf=1ll*inf*inf; struct kdnode { int x[D]; int split; int l,r,p; } kdtree[N],q[N]; bool operator==(const kdnode &a,const kdnode &b) { for(int i=0; i<D; i++) { if(a.x[i]!=b.x[i])return false; } return true; } double avg[D],var[D]; int n; void calAvg(int l,int r) { for(int i=0; i<D; i++)avg[i]=0; for(int i=l; i<=r; i++) for(int j=0; j<D; j++) avg[j]+=1.0*kdtree[i].x[j]/(r-l+1); } void calVar(int l,int r) { for(int i=0; i<D; i++)var[i]=0; for(int i=l; i<=r; i++) for(int j=0; j<D; j++) var[j]+=1.0*(kdtree[i].x[j]-avg[j])/n*(kdtree[i].x[j]-avg[j]); } int splitD; double maxVar; bool cmp(kdnode a,kdnode b) { return a.x[splitD]<b.x[splitD]; } int construct(int p,int l,int r) { if(r<l)return -1; int root=(l+r)/2; calAvg(l,r); calVar(l,r); maxVar=-1.0; for(int i=0; i<D; i++) if(var[i]>maxVar) maxVar=var[i],splitD=i; sort(kdtree+l,kdtree+r+1,cmp); kdtree[root].split=splitD; kdtree[root].l=construct(root,l,root-1); kdtree[root].r=construct(root,root+1,r); kdtree[root].p=p; return root; } int Find(int root,kdnode x) { if(root==-1)return -1; if(x==kdtree[root]) { return root; } int d=kdtree[root].split; if(x.x[d]>kdtree[root].x[d]) { return Find(kdtree[root].r,x); } else if(x.x[d]<kdtree[root].x[d]) { return Find(kdtree[root].l,x); } else { int l=Find(kdtree[root].l,x); int r=Find(kdtree[root].r,x); return (l==-1?r:l); } } int FindMin(int root,int d) { int ret=root; if(kdtree[root].l!=-1) { int v=FindMin(kdtree[root].l,d); if(kdtree[ret].x[d]>kdtree[v].x[d]) ret=v; } if(kdtree[root].r!=-1) { int v=FindMin(kdtree[root].r,d); if(kdtree[ret].x[d]>kdtree[v].x[d]) ret=v; } return ret; } int FindMax(int root,int d) { int ret=root; if(kdtree[root].l!=-1) { int v=FindMax(kdtree[root].l,d); if(kdtree[ret].x[d]<kdtree[v].x[d]) ret=v; } if(kdtree[root].r!=-1) { int v=FindMax(kdtree[root].r,d); if(kdtree[ret].x[d]<kdtree[v].x[d]) ret=v; } return ret; } void DeleteNode(int v) { int p=kdtree[v].p; kdtree[v].p=-1; if(kdtree[p].l==v) kdtree[p].l=-1; else kdtree[p].r=-1; } void Remove(int root,kdnode x) { int pos=Find(root,x); if(kdtree[pos].l==-1&&kdtree[pos].r==-1) { DeleteNode(pos); } else if(kdtree[pos].l==-1) { int alt=FindMin(kdtree[pos].r,kdtree[pos].split); for(int i=0; i<D; i++)kdtree[pos].x[i]=kdtree[alt].x[i]; Remove(alt,kdtree[alt]); } else { int alt=FindMax(kdtree[pos].l,kdtree[pos].split); for(int i=0; i<D; i++)kdtree[pos].x[i]=kdtree[alt].x[i]; Remove(alt,kdtree[alt]); } } void Insert(int root,int x) { int d=kdtree[root].split; if(kdtree[root].x[d]<kdtree[x].x[d]) { if(kdtree[root].r==-1) { kdtree[root].r=x; kdtree[x].p=root; } else Insert(kdtree[root].r,x); } else { if(kdtree[root].l==-1) { kdtree[root].l=x; kdtree[x].p=root; } else Insert(kdtree[root].l,x); } } void Add(int root,kdnode x) { int pos=n; kdtree[n++]=x; Insert(root,pos); } long long dist(kdnode a,kdnode b) { long long ret=0; for(int i=0; i<D; i++) { ret+=1ll*(a.x[i]-b.x[i])*(a.x[i]-b.x[i]); } return ret; } long long query(int root,kdnode x) { if(root==-1)return Inf; int d=kdtree[root].split; long long ret; if(x.x[d]<kdtree[root].x[d]) { ret=query(kdtree[root].l,x); double dd=1.0*x.x[d]+sqrt(1.0*ret); if(dd>=1.0*kdtree[root].x[d]) { ret=min(ret,query(kdtree[root].r,x)); } } else if(x.x[d]>kdtree[root].x[d]) { ret=query(kdtree[root].r,x); double dd=1.0*x.x[d]-sqrt(1.0*ret); if(dd<=1.0*kdtree[root].x[d]) { ret=min(ret,query(kdtree[root].l,x)); } } else { ret=query(kdtree[root].l,x); ret=min(ret,query(kdtree[root].r,x)); } ret=min(ret,dist(kdtree[root],x)); return ret; } int main() { // freopen("in","w",stdout); int t; long long px,py; long long ax,bx,cx,ay,by,cy; scanf("%d",&t); while(t--) { scanf("%d",&n); px=py=0; scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&ax,&bx,&cx,&ay,&by,&cy); px=(ax*px+bx)%cx; py=(ay*py+by)%cy; // puts("fdsf"); for(int i=0; i<1; i++) { kdtree[i].split=0; kdtree[i].p=kdtree[i].l=kdtree[i].r=-1; kdtree[i].x[0]=px; kdtree[i].x[1]=py; q[i]=kdtree[i]; // cout<<px<<" "<<py<<endl; } int root=construct(-1,0,0); px=(ax*px+bx)%cx; py=(ay*py+by)%cy; q[1].split=0; q[1].p=q[1].l=q[1].r=-1; q[1].x[0]=px; q[1].x[1]=py; // cout<<px<<" "<<py<<endl; long long mindis=query(root,q[1]); long long ans=mindis; Add(root,q[1]); // cout<<mindis<<endl; // printf("%I64d\n",mindis); int m=n; for(int i=3; i<m; i++) { // printf("%d %d\n",i,n); px=(ax*px+bx)%cx; py=(ay*py+by)%cy; q[i].split=0; q[i].p=q[i].l=q[i].r=-1; q[i].x[0]=px; q[i].x[1]=py; mindis=min(mindis,query(root,q[i])); if(mindis==0LL)break; ans+=mindis; Add(root,q[i]); } printf("%I64d\n",ans); } return 0; }
不淡定了....