• 考前模拟冲刺 3


    NOIP#17模拟赛

        

    共3道题目,时间3小时

    题目非原创,仅限校内交流使用

     

     

     

    题目名称

    Graph

    Incr

    Permutation

    文件名

    graph

    incr

    permutation

    输入文件

    graph.in

    incr.in

    permutation.in

    输出文件

    graph.out

    incr.out

    permutation.out

    时间限制

    1000ms

    1000ms

    1000ms

    内存限制

    256mb

    256mb

    256mb

    测试点数目

    10

    10

    10

    测试点分值

    10

    10

    10

    是否有部分分

    题目类型

    传统

    传统

    传统

    评测环境

     

    操作系统:Windows XP Professional SP3

    CPU: Intel(R) Pentium(R) CPU G2030 @ 3.00GHz (2CPUs)

    系统内存:2GB

    评测工具:Cena 0.8.1

    Problem 1 Graph (graph.cpp/c/pas)

    题目描述:

    给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点。

    输入格式:

    1 行,2 个整数 N,M。 接下来 M 行,每行 2 个整数 Ui,Vi,表示边 ⟨Ui,Vi⟩。点用 1,2,...,N 编号。

    输出格式:

    N 个整数 A(1),A(2),...,A(N)。

    样例输入:

    4 3
    1 2
    2 4
    4 3

    样例输出:

    4 4 3 4

    数据范围:

    对于 60% 的数据,1 ≤ N,K ≤ 10^3
    对于 100% 的数据,1 ≤ N,M ≤ 10^5

    tarjn加dfs。

    因为tarjin中的

    col[stack[top]]=sumcol;写成了
    col[stack[top]]=now;
    挂了一半的点,要注意!!!!!!!!
    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100001
    using namespace std;
    map<int,int>ma[MAXN];
    int n,m;
    int tot,tot1;
    int tim,top,sumcol;
    int col[MAXN],dis[MAXN];
    int ans[MAXN],into[MAXN],vis[MAXN];
    int to[MAXN],net[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],head1[MAXN];
    int low[MAXN],dfn[MAXN],stack[MAXN],visstack[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v){
        to1[++tot1]=v;net1[tot1]=head1[u];head1[u]=tot1;
    }
    int tarjin(int now){
        low[now]=dfn[now]=++tim;
        stack[++top]=now;
        vis[now]=1;
        visstack[now]=1;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(dfn[now]==low[now]){
            sumcol++;
            col[now]=sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;
            }
            visstack[now]=0;
            top--;
        }
    }
    void dfs(int now){
        for(int i=head1[now];i;i=net1[i]){
            dfs(to1[i]);
            dis[now]=max(dis[now],dis[to1[i]]);
        }
    }
    int main(){
        freopen("graph.in","r",stdin);
        freopen("graph.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        add1(col[i],col[to[j]]);
                        into[col[to[j]]]++;
                    }
        for(int i=1;i<=n;i++)
            dis[col[i]]=max(dis[col[i]],i);
        for(int i=1;i<=sumcol;i++)
            if(!into[i])
                dfs(i);
        for(int i=1;i<=n;i++)
            cout<<dis[col[i]]<<" ";
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    Problem 2 Incr(incr.cpp/c/pas)

    题目描述:

    数列 A1,A2,...,AN,修改最少的数字,使得数列严格单调递增。

    输入格式:

    1 行,1 个整数 N 
    第 2 行,N 个整数 A1,A2,...,AN

    输出格式:

    1 个整数,表示最少修改的数字

    样例输入:

    3
    1 3 2

    样例输出:

    1

    数据范围:

    对于 50% 的数据,N ≤ 10^3 
    对于 100% 的数据,1 ≤ N ≤ 10^5,1 ≤ Ai ≤ 10^9

    数组开小了,gg,找一个最长严格上升子序列。

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int maxn=100005;
    const int oo=0x3fffffff;//极大值
    int a[maxn];
    int lis[maxn], pos[maxn];
    int main(){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        int top=0;
        lis[0]=-oo;
        for(int i=1;i<=n;i++){
            if(a[i]>lis[top]&&a[i]-lis[top]-1>=i-pos[top]-1){
                lis[++top]=a[i];
                pos[top]=i;
            }
            else{
                int l=0, r=top, tp=-1;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(a[i]-lis[mid]-1>=i-pos[mid]-1){
                        tp=mid;
                        l=mid+1;
                    }
                    else r=mid-1;
                }
                if(tp!=-1) lis[tp+1]=a[i], pos[tp+1]=i;
            }
        }
        cout<<n-top<<endl;
    }
        return 0;
    }

    Problem 3 Permutation (permutation.cpp/c/pas)

    题目描述:

    1 到 N 任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。
    问在所有排列中,有多少个排列恰好有K个“<”。 
    例如排列(3, 4, 1, 5, 2) 
    3 < 4 > 1 < 5 > 2 
    共有2个“<”

    输入格式:

    N,K

    输出格式:

    答案

    样例输入:

    5 2

    样例输出:

    66

    数据范围:

    20%:N <= 10 
    50%:答案在0..2^63-1内 
    100%:K < N <= 100
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 1001 
    using namespace std;
    int n,k;
    int c1[MAXN],c2[MAXN];
    struct nond{
        int num[1000];
    }f[101][101];
    void mul1(int lena1,int q,int aa,int bb){
        memset(c1,0,sizeof(c1));
        for(int i=0;i<=lena1;i++)
            c1[i]=f[aa-1][bb-1].num[i];
        for(int i=1;i<=lena1;i++)
            c1[i]*=q;
         for(int i=1;i<=lena1;i++){
            if(c1[i]>=10){
                if(i==lena1)    lena1++;
                c1[i+1]+=c1[i]/10;
                c1[i]%=10;
            }
        }
        for(;lena1>=1;lena1--)    if(c1[lena1]!=0)    break;
        c1[0]=lena1;
    }
    void mul2(int lena2,int q,int aa,int bb){
        memset(c2,0,sizeof(c2));
        for(int i=0;i<=lena2;i++)
            c2[i]=f[aa-1][bb].num[i];
        for(int i=1;i<=lena2;i++)
            c2[i]*=q;
        for(int i=1;i<=lena2;i++){
            if(c2[i]>=10){
                if(i==lena2)    lena2++;
                c2[i+1]+=c2[i]/10;
                c2[i]%=10;
            }
        }
        for(;lena2>=1;lena2--)    if(c2[lena2]!=0)    break;
        c2[0]=lena2;
    }
    void jia(int aa,int bb){
        c1[0]=max(c1[0],c2[0]);
        for(int i=1;i<=c1[0];i++)    c1[i]+=c2[i];
        for(int i=1;i<=c1[0];i++)
            if(c1[i]>=10){
                if(i==c1[0])    c1[0]++;
                c1[i+1]+=c1[i]/10;
                c1[i]%=10;
            }
        for(;c1[0]>=1;c1[0]--)    if(c1[0]!=0)    break;
        for(int i=0;i<=c1[0];i++)    f[aa][bb].num[i]=c1[i];
    }
    int main(){
        freopen("permutation.in","r",stdin);
        freopen("permutation.out","w",stdout);
        scanf("%d%d",&n,&k);
        f[1][0].num[1]=1;f[1][0].num[0]=1;
        f[2][0].num[1]=1;f[2][0].num[0]=1;
        f[2][1].num[1]=1;f[2][1].num[0]=1;
        for(int i=3;i<=n;i++)
            f[i][0].num[0]=1,f[i][0].num[1]=1;
        for(int i=3;i<=n;i++)
            for(int j=1;j<i;j++){
                int k=i-j,tot1=0;
                int kk=j+1,tot2=0;
                mul1(f[i-1][j-1].num[0],k,i,j);
                mul2(f[i-1][j].num[0],kk,i,j);
                jia(i,j);
            }
        for(int i=f[n][k].num[0];i>=1;i--)
            cout<<f[n][k].num[i];
    }
    /*
    20 15
    */
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    微服务怎么限流?算法+框架+实战!
    Maven 架构选型,单模块还是多模块?
    Java 几行代码提取图片文字,过个厉害了。。
    面试官:SOA 和微服务的区别?这回终于搞清楚了!
    别再纠结线程池大小了,没有固定公式的!终于有人说清楚了。。
    MySQL 8.0 可以操作 JSON 了,牛逼。。。
    C#中判断一个类是否实现了某interface
    所有各数据库或文件的连接串定义CHM文件.
    这两天终于把火箭动力稍微搞清楚了点
    事件查看器中总是出现 sqlserveragent的错误
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7809671.html
Copyright © 2020-2023  润新知