• 第n+1次考试


    题目:

    1. 中位数

    【问题描述】

    给定C个不同物品,每个物品有一重量和体积,保证每个物品的重量不一样。从中选出N个物品,在体积不超过F的情况下,使得选出的物品的重量的中位数最大。所谓中位数,就是排序后处在最中间的重量,比如3,8,9,7,5的中位数是7

    【输入格式】

    第一行:三个用空格分开的整数:NCF≤ ≤ 19999≤ ≤ 105

    ≤ ≤ × 109

    第二行到C + 1行:每行有两个用空格分开的整数。第一个数是这个物品的重量Wi,第二个数是这个物品的体积Qi

    【输出格式】

    第一行:一个整数,表示可以得到的最大中位数,如果F装不下任何N个物品,则输出-1

    【输入样例】

    3 5 70

    30 25

    50 21

    20 20

    5 18

    35 30

    【输出样例】

    35

    【样例解释】

    选择重量为 5, 35, 50 的物品,中位数为 35,体积18 + 30 + 21 = 69,小于70

    【数据范围】

        40%的数据,≤ N≤ 200

    100%的数据,≤ ≤ 19999≤ ≤ 105≤ ≤ × 109≤ Qi≤ 105≤ Wi≤ × 109。保证n为奇数。

     

    2. 爆炸

    【问题描述】

     有N个城市,M条双向道路组成的地图,城市标号为1到N。“西瓜炸弹”放在1号城市,保证城市1至少连接着一个其他城市。“西瓜炸弹”有P/Q的概率会爆炸,每次进入其它城市时,爆炸的概率相同。如果它没有爆炸,它会随机的选择一条道路到另一个城市去,对于当前城市所连接的每一条道路都有相同的可能性被选中。对于给定的地图,求每个城市“西瓜炸弹”爆炸的概率。

    例如,假设只有两个城市1和2,它们被一条道路连接起来。最开始“西瓜炸弹”放在城市1,每次进入城市它都有1/2的可能性爆炸: 

    1 — 2

    我们就有以下可能的路径(其中最后一项是结束城市,即“西瓜炸弹”爆炸并污染该城市): 

    1: 1 
    2: 1-2 
    3: 1-2-1 
    4: 1-2-1-2 
    5: 1-2-1-2-1 
    etc. 

    为了找出“西瓜炸弹”在城市1爆炸的可能性,我们可以把第1、3、5…种路径出现的概率加起来(在这个例子中即把所有奇数路径出现的可能性加起来)。 
    对于第k种路径出现的可能性为(1/2)^k:在经过前k-1次时,炸弹绝对不会在城市1爆炸(每一次的概率为1 – 1/2 = 1/2),然后最后在城市1爆炸(概率为1/2)。 

    因此,在城市1爆炸的可能性就是 1/2 + (1/2)^3 + (1/2)^5 + … ,把这些数都加起来就等于2 / 3,约为0.666666667。 
    所以在城市2爆炸的可能性就是1/3,约为0.333333333。

    【输入格式】

    第1行:四个被空格分隔整数:N,M,P和Q 

    第2..M+1行:第i行描述了两个空格分隔的整数:A_j 和 B_j(表示城市A_j与B_j相连)

    【输出格式】

    第1..N行:第i行为一个小数,表示第i个城市 “西瓜炸弹”爆炸的概率。至少要精确到10^-6才有效。

    【输入样例1】

    2 1 1 2 
    1 2

    【输出样例1】

    0.666666667 
    0.333333333

    【输入样例2】

    3 2 1 3

    1 2

    3 2

    【输出样例2】

    0.466666667

    0.400000000

    0.133333333

    【数据范围】

    20%  2<=N<=25 , 1<=M<=100

    100% 2 <= N <= 300 ,1 <= M <= 44850 ,1 <= P <= 1,000,000,1 <= Q <= 1,000,000

    3.序列划分

    【题目描述】

    给定一个序列{An},现在,需要把这个序列划分成K个子序列,使得每个子序列包含的数的个数不少于2,并且要么非升,要么非降。你的任务就是求出K的最小值。

    【输入文件】

    输入第一行一个正整数N,表示序列长度,接下来N行,第i行表示元素Ai-1

    【输出文件】

    如果不能划分这个序列,输出一个数0;否则输出K

    【样例输入1

    6

    12

    33

    97

    18

    15

    33

    【样例输出1

    2

    【样例输入2

    1

    88

    【样例输出2

    0

    【样例输入3

    4

    77

    22

    22

    11

    【样例输出3

    1

    【数据规模】

    对于30%的数据,1<=N<=10

    对于100%的数据,1<=N<=251<=Ai<=100

     题解:

    一:按照体积排序

    1.预处理前i小、大的体积的物品的重量拿n/2个的最小重量

    然后一个个枚举过去,看看是否成立

    至于预处理就用一个堆好了

    二:高斯消元+概率dp

    本来想要简单的dp+收敛,没有想到数据那么坑。。。

    (其实按照随机的概率大概可以过p/q>0.02的情况吧)

    正解:高斯校园+概率

    列出n个方程,解n个数字,就是高斯消元

    三:迭代深搜

    枚举有多少个可以,然后按照类似与导弹拦截的贪心方法做贪心

    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=200005;
    int f[N],d[N],l,a[N],b[N],n,m,F;
    long long f1[N],f2[N];
    void up(int x)
    {
        if (x==1)return;
        if (d[x]>d[x/2])
         {
             swap(d[x],d[x/2]);
             up(x/2);
         }
    }
    void down(int x)
    {
        int i=x;
        if (x*2<=l&&d[x]<d[x*2])i=x*2;
        if (x*2<l&&d[i]<d[x*2+1])i=x*2+1;
        if (i!=x)
         {
             swap(d[x],d[i]);
             down(i);
         }
    }
    int cmp(int x,int y)
    {
        return a[x]<a[y];
    }
    int main()
    {
        freopen("finance.in","r",stdin);
        freopen("finance.out","w",stdout); 
        scanf("%d%d%d",&n,&m,&F);
        for (int i=1;i<=m;i++)scanf("%d%d",&a[i],&b[i]),f[i]=i;
        sort(f+1,f+m+1,cmp);
        for (int i=1;i<=n/2;i++)d[i]=b[f[i]],f1[i]=f1[i-1]+b[f[i]];
        l=n/2;
        for (int i=1;i<=n/2;i++)up(i);
        for (int i=n/2+1;i<=m;i++)
         {
             if (b[f[i]]>=d[1])
              {
                  f1[i]=f1[i-1];
                  continue;
              }
             f1[i]=f1[i-1]+b[f[i]]-d[1]; 
             d[1]=b[f[i]];
            down(1); 
         }
        memset(d,0,sizeof d);
        for (int i=m;i>m-n/2;i--)d[m-i+1]=b[f[i]],f2[i]=f2[i+1]+b[f[i]];
        for (int i=1;i<=n/2;i++)up(i);    
        for (int i=m-n/2;i;i--)
         {
             if (b[f[i]]>=d[1])
              {
                  f2[i]=f2[i+1];
                  continue;
              }
             f2[i]=f2[i+1]+b[f[i]]-d[1]; 
             d[1]=b[f[i]];
            down(1);          
         }  
        for (int i=m-n/2;i>n/2;i--)
         if (F>=f1[i-1]+f2[i+1]+b[f[i]])
          {
              printf("%d",a[f[i]]);
              return 0;
          }
        puts("-1");
        return 0;  
    } 
    #include <bits/stdc++.h>
    using namespace std;
    typedef double ld;
    const int N=305;
    const ld eps=1e-15;
    int n,m,mp[N][N],du[N];
    ld f[N][N],sum,P,Q;
    int main()
    {
        freopen("dotp.in","r",stdin);
        freopen("dotp.out","w",stdout);
        scanf("%d%d%lf%lf",&n,&m,&P,&Q);
        for(int i=1,x,y;i<=m;i++)
         {
            scanf("%d%d",&x,&y);
            mp[x][y]++;mp[y][x]++;
            du[x]++;du[y]++;
         }
        f[1][n+1]=1;
        for(int i=1;i<=n;i++)
         {
            f[i][i]=1;
            for(int j=1;j<=n;j++)
             if(mp[i][j])f[i][j]+=((ld)P/Q-1)/du[j]*mp[i][j];
         }
        for(int i=1;i<=n;i++)
         {
            int t=i;
            for(int j=i;j<=n;j++)
             if(fabs(f[j][i])>eps)t=j;
            for(int j=1;j<=n+1;j++)swap(f[i][j],f[t][j]);
            for(int j=1;j<=n;j++)
             if(j!=i&&fabs(f[j][i])>eps)
              {
                ld t=f[j][i]/f[i][i];
                for(int k=1;k<=n+1;k++)f[j][k]-=f[i][k]*t;
              }
         }
        for(int i=1;i<=n;i++)sum+=(f[i][i]=f[i][n+1]/f[i][i]);
        for(int i=1;i<=n;i++)printf("%.9lf
    ",(double)(f[i][i]/sum+eps));
        return 0;
    }
    #include<bits/stdc++.h>
    using namespace std;
    const int N=30;
    int a[N][N],b[N][N],A,B,ans[N],x[N],dep,n;
    void DFS(int u)
    {
        if (A+B>dep)return;
        if (u>n)
         {
            for (int i=1;i<=A;i++)
             if (*a[i]<2)return;
            for (int i=1;i<=B;i++)
             if (*b[i]<2)return;
            printf("%d
    ",dep);
            exit(0);
         }
        int v=0;
        for (int i=1;i<=A;i++)
         if (a[i][*a[i]]<=x[u]&&(!v||a[v][*a[v]]<a[i][*a[i]]))v=i;
        if (!v)
         {
            ++A;
            a[A][++*a[A]]=x[u];
            ans[u]=A;
            DFS(u+1);
            --*a[A--];
         }
        else
         {
            a[v][++*a[v]]=x[u];
            ans[u]=v;
            DFS(u+1);
            --*a[v];
         }
        v=0;
        for (int i=1;i<=B;i++)
         if (b[i][*b[i]]>=x[u]&&(!v||b[v][*b[v]]>b[i][*b[i]]))v=i;
        if (!v)
         {
            ++B;
            b[B][++*b[B]]=x[u];
            ans[u]=dep+1-B;
            DFS(u+1);
            --*b[B--];
         }
        else
         {
            b[v][++*b[v]]=x[u];
            ans[u]=dep+1-v;
            DFS(u+1);
            --*b[v];
         }
    }
    int main()
    {
        freopen("sequence.in","r",stdin);
        freopen("sequence.out","w",stdout);
        scanf("%d",&n);
        for (int i=1;i<=n;i++)scanf("%d",&x[i]);
        for (dep=1;dep*2<=n;dep++)
          {
            memset(a,0,sizeof a);
            memset(b,0,sizeof b);
            A=B=0;
            DFS(1);
         }
        puts("0");    
        return 0;
    }
  • 相关阅读:
    环求解点值
    汉诺塔(记录每种路径次数)
    快速排序
    选择排序
    冒泡排序
    桶排序
    异或后最大lowerbit
    计数三角形
    nico和niconiconi
    提高程序设计能力的一般方法
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/7642870.html
Copyright © 2020-2023  润新知