BestCoder Round #76 (div.2)

链接:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=679

题意:有n个球,从盒子中挑两个球出来。先均匀随机地从盒子中挑出一个球,记为A。不把A放回盒子,然后再从盒子中均匀随机地挑出一个球,记为B。
求出A上的数字严格大于B上的数字的概率是。

分析:记录没个数的个数,暴力枚举A,B,算出情况数,最后除以n*(n-1).

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 2510
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int x,b[Mn];
int main() {
    int T;
    scanf("%d",&T);
    int n;
    while(T--) {
        CLR(b,0);
        scanf("%d",&n);
        for(int i=0;i<n;i++) {
            scanf("%d",&x);
            b[x]++;
        }
        int ans=0;
        for(int i=300;i>0;i--) {
            int t=0;
            if(b[i]) for(int j=i-1;j>=0;j--)
                if(b[j])t+=b[i]*b[j];
            if(t) ans+=t;
        }
        printf("%.6f\n",(double)ans/n/(n-1));
    }
    return 0;
}


题意:把n拆成k个不重复的正整数之和。输出这k个数最大乘积。

分析:我们可以知道连续的数乘积最大,记sum(a,k)=a+(a+1)+⋯+(a+k−1),可知k*(k+1)/2>n是不可拆分的,所以k最大10^5。

sum(a,k)<=n  -> a*k+k*(k-1)<=n  ->  a<=n/k-(k-1)/2,可以求出a来,这时可能多出一些数,从后往前每个加1,加上多出来的数。

然后相乘。.

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1001000
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int main() {
    int t,n,k;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&k);
        if((ll)k*(k+1)/2>n) {
            printf("-1\n");
            continue;
        }
        int a=(int)((double)n/k-((double)k-1)/2);
        int ha=n-a*k-k*(k-1)/2;
        ll ans=1;
        int ed=k-ha;
        for(int i=1;i<=ed;i++) {
            ans=(ans*(a+i-1))%mod;
        }
        for(int i=ed+1;i<=k;i++) {
            ans=(ans*(a+i))%mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


题意:求每个点所在的连通集的大小和。

分析:令siz[i]表示以i为根的子树方案数,sum[i]表示以i为根对答案做的贡献。

  sum[u]=((ll)sum[u]*(siz[v]+1))%mod;  //之前子树的大小会变成*(siz[v]+1)种可行方案 因为每个元素都能在子结点的集合里出现一次
  sum[u]=((ll)sum[u]+(ll)siz[u]*sum[v])%mod;//新的子树(y)大小会变成siz
[u]*sum[v]种可行方案  因为每个子结点的元素都能在 u 的集合里出现一次。

  siz[u]=((ll)siz[u]*(siz[v]+1))%mod;//子树大小会变成*(siz[v]+1)种 

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 200010
#define Mm 300010
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int read() {
    char c=getchar();
    int re=0,f=1;
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') {re=re*10+c-'0';c=getchar();}
    return re*f;
}
struct edge {
    int v,next;
}e[Mm];
int head[Mn],tot;
void addedge(int u,int v) {
    e[tot].v=v;
    e[tot].next=head[u];
    head[u]=tot++;
}
int n,m,siz[Mn],sum[Mn];
void dfs(int u,int fa) {
    siz[u]=1;sum[u]=1;
    for(int i=head[u];~i;i=e[i].next) {
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u);
        sum[u]=((ll)sum[u]*(siz[v]+1))%mod;
        sum[u]=((ll)sum[u]+(ll)siz[u]*sum[v])%mod;
        siz[u]=((ll)siz[u]*(siz[v]+1))%mod;
    }
}
void init() {
    CLR(head,-1);
    tot=0;
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        init();
        n=read();
        for(int i=2;i<=n;i++) {
            int u=read();
            addedge(i,u);
            addedge(u,i);
        }
        dfs(1,0);
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans=(ans+sum[i])%mod;
        cout<<ans<<endl;
    }

    return 0;
}


你可能感兴趣的:(BestCoder Round #76 (div.2))