• 【NOIP2013】DAY1题解+代码


    T1

    傻逼快速幂,敲敲就过了。

    我跟你们讲个笑话当时我以为这个数据范围过不了于是想出了求GCD再推规律什么的magic方法中途还咨询了某个学长。

    然后怎么想都是不可做。

    ……直到我发现我昨年的代码一个傻逼快速幂就过了=A=

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n=0,m=0,k=0,x=0;
    long long quick(int x,int y);
    int main(void)
    {
        freopen("circle.in","r",stdin);
        freopen("circle.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&k,&x);
        long long ans=quick(10,k);
        ans=ans*m%n;
        ans=(ans+x)%n;
        printf("%lld",ans);
        return 0;
    }
    
    long long quick(int x,int y)
    {
        if(y==1)return x;
        int ins=y/2;
        long long tot=0ll;
        tot=quick(x,ins)%n;
        tot=tot*tot%n;
        if(y%2)tot=tot*x%n;
        return tot;
    }
    View Code

    T2

    排个序,离散化之后找逆序对即可。

    这里要注意的是,我们先把两个数列离散化+排序之后,是找第二个数列里的数在第一个数列里出现的位置,然后对这个序列求逆序对。

    我为了这个映射卖了很多蠢就不说了。

    我会说因为我不想写归并于是用了树状数组求逆序对?

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    struct line
    {
        int sum;
        int num;
    };
    line xl_a[100003],xl_b[100003];
    int n=0,stack[100003]={0},top=0;
    int mark[100003]={0},tree[100003]={0}; 
    const int mod=99999997;
    bool cmp(line a,line b);
    bool kp(line a,line b);
    int lowbit(int x);
    int red(int x);
    void add(int x);
    int main(void)
    {
        freopen("match.in","r",stdin);
        freopen("match.out","w",stdout); 
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&xl_a[i].sum),xl_a[i].num=i;
        sort(xl_a+1,xl_a+n+1,cmp);
        for(int i=1;i<=n;i++)xl_a[i].sum=i;
        
        for(int i=1;i<=n;i++)scanf("%d",&xl_b[i].sum),xl_b[i].num=i;
        sort(xl_b+1,xl_b+n+1,cmp);
        for(int i=1;i<=n;i++)xl_b[i].sum=i;
        
        
        sort(xl_b+1,xl_b+n+1,kp);
        for(int i=1;i<=n;i++)mark[i]=xl_a[xl_b[i].sum].num; 
        
        long long ans=0;
        
        for(int i=1;i<=n;i++)
        {
            ans+=red(n)-red(mark[i]);
            ans%=mod;
            add(mark[i]);
        } 
        printf("%d",ans);
        return 0;
    }
    
    bool cmp(line a,line b)
    {
        if(a.sum<b.sum)return 1; 
        return 0;
    } 
    
    bool kp(line a,line b)
    {
        if(a.num<b.num)return 1;
        return 0;
    }
    
    int lowbit(int x){return x&-x;}
    
    int red(int x)
    {
        int tot=0;
        while(x)
        {
            tot+=tree[x];
            tot%=mod;
            x-=lowbit(x);
        }
        return tot;
    }
    
    void add(int x)
    {
        while(x<=n)
        {
            tree[x]++;
            tree[x]%=mod;
            x+=lowbit(x);
        }
    }
    View Code

    T3

    最大生成树+树上倍增标准模板

    调了半小时发现我预处理写错了。

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    struct bian
    {
        int x;
        int y;
        int v;
    };
    bian a[100003];//因为我们是存储双向边所以边数量x2
    struct lb
    {
        int u;
        int to;
        int val;
    };
    lb line[20003];
    int head[10003]={0},fa[10003]={0},n=0,m=0,q=0;
    int cnt_1=0,cnt_2=0,deep[10003]={0};
    int beiz[10003][21]={0},value[10003][21]={0};
    //最大生成树函数x3 
    void kruskal();
    int fid(int x);
    void heb(int x,int y);
    //树上倍增
    void dfs(int nw);//确定树 
    void pre(int x);//倍增预处理 
    int ask(int x,int y);//查询两点之间的公共祖先
    //乱七八糟的函数
    void add(int f,int t,int val); 
    bool cmp(bian A,bian B);
    int main(void)
    {
        freopen("truck.in","r",stdin);
        freopen("truck.out","w",stdout);
        scanf("%d%d",&n,&m);
        int b=0,c=0,d=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&b,&c,&d);
            cnt_1++;
            a[cnt_1].x=b,a[cnt_1].y=c,a[cnt_1].v=d;
            swap(b,c);
            cnt_1++;
            a[cnt_1].x=b,a[cnt_1].y=c,a[cnt_1].v=d;
        }
        sort(a+1,a+cnt_1+1,cmp);
        for(int i=1;i<=n;i++)fa[i]=i; 
        kruskal();
        memset(beiz,-1,sizeof(beiz));
        beiz[1][0]=1,value[1][0]=0x7ffffff,deep[1]=0; 
        dfs(1);
        pre(1);
        scanf("%d",&q);//我觉得是根节点的问题…… 
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&b,&c);
            if(beiz[b][0]==-1||beiz[c][0]==-1)
            {
                printf("-1
    ");
                continue;
            }
            printf("%d
    ",ask(b,c));
        }
        return 0; 
    }
    bool cmp(bian A,bian B)
    {
        if(A.v>B.v)return 1;
        return 0;
    }
    
    int fid(int x)
    {
        if(fa[x]==x)return x;
        fa[x]=fid(fa[x]);
        return fa[x];
    }
    
    void heb(int x,int y)
    {
        fa[x]=y;
        return;
    }
    
    void kruskal()
    {
        int cho=0,f_x=0,f_y=0;
        for(int i=1;i<=cnt_1;i++)
        {
            if(cho==n-1)break;
            f_x=fid(a[i].x);
            f_y=fid(a[i].y); 
            if(f_x==f_y)continue;
            cho++;
            add(a[i].x,a[i].y,a[i].v);
            add(a[i].y,a[i].x,a[i].v);
            heb(f_x,f_y);
        } 
        return;    
    }
    
    void add(int f,int t,int val)
    {
        line[++cnt_2].u=t;
        line[cnt_2].to=head[f];
        line[cnt_2].val=val;
        head[f]=cnt_2;
        return;
    }
    
    void dfs(int nw)
    {
        if(nw>n)return;
        int next=0; 
        for(int i=head[nw];i>0;i=line[i].to)
        {
            next=line[i].u;
            if(next==beiz[nw][0])continue;
            beiz[next][0]=nw;
            value[next][0]=line[i].val;
            deep[next]=deep[nw]+1;
            dfs(next);
        }
        return;
    }
    
    void pre(int nw)
    {
        if(nw>=20)return;
        for(int i=1;i<=n;i++)
        {
            beiz[i][nw]=beiz[beiz[i][nw-1]][nw-1];
            value[i][nw]=min(value[i][nw-1],value[beiz[i][nw-1]][nw-1]);
        }
        pre(nw+1); 
        return;
    }
    
    int ask(int x,int y) 
    {
        if(deep[x]<deep[y])swap(x,y);
        int ans=0x7fffffff;
        for(int i=19;i>=0;i--)if(deep[x]-(1<<i)>=deep[y])ans=min(ans,value[x][i]),x=beiz[x][i];
        if(x==y)return ans;
        for(int i=19;i>=0;i--)
        {
            if(beiz[x][i]!=beiz[y][i])
            {
                ans=min(ans,value[x][i]);
                x=beiz[x][i];
                ans=min(ans,value[y][i]);
                y=beiz[y][i];
            }
        }
        ans=min(ans,value[x][0]);
        ans=min(ans,value[y][0]);
        return ans;
    }
    View Code
  • 相关阅读:
    Python开发——数据类型【字典】
    Python开发——数据类型【元祖】
    Python开发——数据类型【列表】
    Python开发——基础
    Python开发——数据类型【运算符】
    c#中IList<T>与List<T>
    观察者模式(Observer Pattern)
    中介者模式(Mediator Pattern)
    策略模式(Strategy Pattern)
    命令模式
  • 原文地址:https://www.cnblogs.com/CYWer/p/6054662.html
Copyright © 2020-2023  润新知