• BJOI2014 想法


    Description

    小强和阿米巴是好朋友。

    小强要出一套题目。他的题目以涉及面广(偏)、考察深入(怪)、思维强度大(难)著称。他为了出题,一共攒了M个本质不同的想法,每个想法形成了一个题目。不过,他觉得拿这些题目去考察选手会把比赛搞的太过变态,所以,想请阿米巴来帮忙调整一下他的题目。

    阿米巴指出,为了让一场考试的题目的考察点尽量全面,有一个通用的做法叫做“组合”。如果把两个题目A和B组合在一起,那么组合而成的题目涉及到的想法的集合就是A涉及到的想法的集合和B涉及到的想法的集合的并。

    并且,题目是可以反复组合的。

    例如,小强现在有三个想法1,2,3,分别对应了题目P1,P2,P3。

    现在,小强把P1和P2组合得到P4。P4涉及的想法的集合是{1,2}。

    之后,小强把P2和P3组合得到P5。P5涉及的想法的集合是{2,3}。

    最后,小强把P4和P5组合得到P6。P6涉及的想法的集合是{1,2,3}。

    现在,小强告诉你每个题目都是如何组合而来的。你要回答的就是,每个题目涉及的想法的集合有多大。

    不过,这个问题是很难的。于是,你只需要能够以比较高的概率回答的比较准确即可。
     

    Input

    第一行两个整数N,M,依次表示小强的题目数量和想法的数量

    接下来N-M行,每行两个整数,依次表示小强组合出来的题目都是由哪两个题组合而成的。M个想法对应的题目依次编号为1~M。之后,小强组合出来的第一个题编号为M+1,组合出来的第二个题编号为M+2,依次类推。

    Output

    输出N-M行,每行一个整数表示小强组合出来的每个题都涉及了几个想法。
     

    Sample Input

    6 3

    1 2

    2 3

    4 5

    Sample Output

    2

    2

    3
     

    Data Constraint

    对于30%的数据,M≤1000,N≤10000

    对于60%的数据,M≤10000,N≤100000

    对于100%的数据,M≤100000,N≤1000000
     

    Hint

    【评分方法】

    对于每个输出文件,如果其中你有95%以上的行的答案和正确答案的误差不超过25%,那么你就可以得到分数。所谓误差不超过25%,即,如果正确答案是X,那么你的答案在[0.8X,1.25X]这个闭区间内。

    60分直接压位即可

    接下来说说满分的神级做法:

    随机大法!

    对于每个想法Random一个随机器代表它,合并的时候保留前T小的数。最后的答案即是T*RAND_MAX/(第T小的数)

    为什么这样可以呢?

    设包含的总想法数为L,在L中取到T的期望为T/L,而随机数是均匀分布的,所以T/L会等于RAND_T/RAND_MAX,所以L=T*RAND_MAX/RAND_T

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    
    using namespace std;
    
    double r;
    
    int son[1000111][2];
    int a[1001111][31];
    int tt,n,m,T,tl,mx,i,x,z,seed,t,lim;
    double ans[1000111];
    
    void cger(int *a,int *b,int *c)
    {
        int j,k,i,al,bl;
        al=1;
        bl=1;
        c[0]=0;
        while(al<=a[0]&&bl<=b[0]){
            if(a[al]<b[bl]){
                if(a[al]!=c[c[0]]){
                    c[0]++;
                    c[c[0]]=a[al];
                }
                al++;
            }
            else{
                if(b[bl]!=c[c[0]]){
                    c[0]++;
                    c[c[0]]=b[bl];
                }
                bl++;
            }
            if(c[0]==lim)break;
        }
        if(c[0]!=lim){
            while(al<=a[0]){
                if(a[al]!=c[c[0]]){
                    c[0]++;
                    c[c[0]]=a[al];
                }
                al++;
                if(c[0]==lim)break;
            }
            while(bl<=b[0]){
                if(b[bl]!=c[c[0]]){
                    c[0]++;
                    c[c[0]]=b[bl];
                }
                bl++;
                if(c[0]==lim)break;
            }
        }
    }
    
    int main()
    {
        srand((unsigned)time(0));
        seed=1;
        scanf("%d%d",&n,&m);
        lim=20;
        for(i=m+1;i<=n;i++){
            scanf("%d%d",&x,&z);
            son[i][0]=x;
            son[i][1]=z;
        }
        T=10000000/n;
        for(tl=1;tl<=T;tl++){
            mx=0;
            for(i=1;i<=m;i++){
                a[i][1]=rand()+1;
                a[i][0]=1;
            }
            for(i=m+1;i<=n;i++)a[i][0]=0;
            for(i=m+1;i<=n;i++){
                cger(a[son[i][0]],a[son[i][1]],a[i]);
                if(a[i][0]<lim)ans[i]+=a[i][0];
                else ans[i]=ans[i]+(double)lim*(double)RAND_MAX/(double)a[i][a[i][0]];
            }
        }
        for(i=m+1;i<=n;i++){
            t=(int)(ans[i]/(double)T+0.001);
            printf("%d
    ",t);
        }
    }
  • 相关阅读:
    Ubuntu上使用Latex
    Ubuntu18.04 解压文件名乱码的解决方法
    Android 编译 opencv
    android 使用编译好的sdk
    https协议加密原理介绍(一)
    java 面试题目 class.forName和load的区别
    给进程设置环境变量
    Maven 编译jdk配置
    Docker积累
    潜谈单例模式
  • 原文地址:https://www.cnblogs.com/applejxt/p/3931746.html
Copyright © 2020-2023  润新知