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);
    }
}
原文地址:https://www.cnblogs.com/applejxt/p/3931746.html