码迷,mamicode.com
首页 > 其他好文 > 详细

XJOI CSP-S2 2019开放模拟训练题1 赛后总结

时间:2019-11-04 22:04:27      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:memset   维护   span   题意   pos   jpg   time   获得   return   

比赛链接

友好数对

暴力枚举\([L,R]\)之间的所有数,将每个数进行"旋转",看是否符合题意.

注意"旋转"的次数,并不一定是数字位数.只要旋转回到了初始数就应该跳出,否则会重复计算.

#include<bits/stdc++.h>
int T,L,R;

int F(int x)
{
    int Len=0;
    while(x){x/=10;Len++;}
    return Len;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&L,&R);
        int Len=F(L),p=1,Ans=0;
        for(int i=1;i<Len;i++)p*=10;
        for(register int A=L;A<=R;A++)
        {
            int B=A;
            while(1)
            {
                B=B/10+p*(B%10);
                if(A<B&&B<=R)++Ans;
                if(A==B)break;
            }   
        }
        printf("%d\n",Ans); 
    }   
    return 0;
} 

路径数

因为Euphemia对于美的追求,"她走过的路径是关于左下 - 右上对角线对称的",我们可以把把右下方一半的图对称到左上方,然后对于每个格子,向它可达的格子连边,再把左上 - 右下对角线上的格子向超级汇点连边,跑一边Dijkstra同时计算最短路条数即可.

但是开始的时候,我把对称那里写成了中心对称,导致爆0.??

菜是原罪

#include<bits/stdc++.h>
const int SIZE=105,N_MAX=10005,M_MAX=80005,Mod=1000000009;
int n,G[SIZE][SIZE],P[SIZE][SIZE],R[N_MAX];
int head[N_MAX],nex[M_MAX],to[M_MAX],Tot;
void Link(int u,int v){nex[++Tot]=head[u];head[u]=Tot;to[Tot]=v;} 
int OFFX[]={0,-1,0,0,1},OFFY[]={0,0,-1,1,0};
bool E(int X,int Y){return (X<1||Y<1||X>n||Y>n||X+Y>n+1)? 0 : 1;}

struct node
{
    int pos,D;
    bool operator <(const node &x)const
    {
        return D>x.D;
    }
};
std::priority_queue<node>q;
bool mk[N_MAX];
int D[N_MAX],F[N_MAX];
void Dijkstra()
{
    memset(D,0x3F,sizeof(D));
    memset(F,0,sizeof(F));
    memset(mk,0,sizeof(mk));
    D[1]=R[1];
    F[1]=1;
    q.push((node){1,D[1]});
    while(q.size())
    {
        int u=q.top().pos;
        q.pop();
        if(mk[u])continue;
        mk[u]=1;
        for(int i=head[u];i;i=nex[i])
        {
            int v=to[i];
            if(D[v]>D[u]+R[v])
            {
                D[v]=D[u]+R[v];
                F[v]=F[u];
                q.push((node){v,D[v]});
            }
            else if(D[v]==D[u]+R[v])
                F[v]=(F[v]+F[u])%Mod;   
        }
    }
}

int main()
{
    while(1)
    {
        scanf("%d",&n);
        if(n==0)break;
        int Tim=0;
        memset(P,0,sizeof(P));
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
            {
                scanf("%d",&G[i][k]);
                P[i][k]=++Tim;
            }   
        ++Tim;
        memset(R,0,sizeof(R));
        for(int i=1;i<=n;i++)
            for(int k=1;k+i<=n+1;k++)
            {
                if(k+i==n+1)R[P[i][k]]=G[i][k];
                else R[P[i][k]]=G[i][k]+G[n-k+1][n-i+1];
            }   
        memset(head,0,sizeof(head));
        Tot=0;
        for(int i=1;i<=n;i++)
            for(int k=1;k+i<=n+1;k++)
            {
                for(int p=1;p<=4;p++)
                {
                    int Xs=i+OFFX[p];
                    int Ys=k+OFFY[p];
                    if(E(Xs,Ys))
                        Link(P[i][k],P[Xs][Ys]);
                }
                if(k+i==n+1)
                    Link(P[i][k],Tim);
            }
        Dijkstra();
        printf("%d\n",F[Tim]);
    }       
    return 0;
}

选信封

打了个DFS套DFS,获得了30分的好成绩.

然后写了个模拟退火,就过了?甚至都没有srand.

此时我的表情是:

技术图片

模拟退火代码(LCT维护连通性):

#include<bits/stdc++.h>
const int SIZE=1500;
#define Random(x) (rand()%x+1)

int n,A[SIZE][5],B[SIZE][5],Tem[SIZE],Ans,now,Tot;

struct LCT
{
    int F[SIZE],C[SIZE][2];
    bool Tag[SIZE];
    #define LC(x) C[x][0]
    #define RC(x) C[x][1]
    bool NRoot(int x){return LC(F[x])==x||RC(F[x])==x;} 
    void Rev(int x){std::swap(LC(x),RC(x));Tag[x]^=1;}
    void push_down(int x){if(Tag[x]){if(LC(x))Rev(LC(x));if(RC(x))Rev(RC(x));Tag[x]=0;}}
    void Rotate(int x)
    {
        int u=F[x],v=F[u],k=(RC(u)==x),w=C[x][k^1];
        if(NRoot(u))C[v][RC(v)==u]=x;C[x][k^1]=u;C[u][k]=w;
        if(w)F[w]=u;F[u]=x;F[x]=v;
    }
    void push(int x){if(NRoot(x))push(F[x]);push_down(x);}
    void Splay(int x)
    {
        for(push(x);NRoot(x);Rotate(x))
            if(NRoot(F[x]))Rotate((LC(F[x])==x)^(LC(F[F[x]])==F[x])?x:F[x]);
    }
    void Access(int u){for(int v=0;u;u=F[v=u])Splay(u),RC(u)=v;}
    void MakeRoot(int x){Access(x);Splay(x);Rev(x);}
    int Find(int x){Access(x);Splay(x);while(LC(x)){push_down(x);x=LC(x);}Splay(x);return x;}
    void Split(int u,int v){MakeRoot(u);Access(v);Splay(v);}
    void Link(int u,int v){MakeRoot(u);if(Find(v)!=u)F[u]=v;}
    void Cut(int u,int v){MakeRoot(u);if(Find(v)==u&&F[v]==u&&!LC(v))F[v]=RC(u)=0;}
}T;

void SA()
{
    for(double Temperature=1000;Temperature>1e-14;Temperature*=0.99)
    {
        int p=Random(n),o=Random(2);
        if(T.Find(A[p][o])!=T.Find(B[p][o]))
        {
            ++now;
            Ans=std::max(Ans,now);
            T.Link(A[p][o],B[p][o]);
        }
        else if(exp(((double)Ans-now)/Temperature)<(double)Random(RAND_MAX)/RAND_MAX)
        {
            T.Cut(A[p][o],B[p][o]);
        }
    }
}

int main()
{
    srand(time(0));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&A[i][1],&B[i][1],&A[i][2],&B[i][2]);
        Tem[++Tot]=A[i][1];
        Tem[++Tot]=B[i][1];
        Tem[++Tot]=A[i][2];
        Tem[++Tot]=B[i][2];
    }
    std::sort(Tem+1,Tem+1+Tot);
    for(int i=1;i<=n;i++)
    {
        A[i][1]=std::lower_bound(Tem+1,Tem+1+Tot,A[i][1])-Tem;
        B[i][1]=std::lower_bound(Tem+1,Tem+1+Tot,B[i][1])-Tem;
        A[i][2]=std::lower_bound(Tem+1,Tem+1+Tot,A[i][2])-Tem;
        B[i][2]=std::lower_bound(Tem+1,Tem+1+Tot,B[i][2])-Tem;
    }
    SA();
    printf("%d",Ans);
    return 0;
} 

XJOI CSP-S2 2019开放模拟训练题1 赛后总结

标签:memset   维护   span   题意   pos   jpg   time   获得   return   

原文地址:https://www.cnblogs.com/TaylorSwift13/p/11794868.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!