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;

}


不淡定了....


 

 


 

你可能感兴趣的:(HDU)