测试 9

 

 

 

思路:一眼秒的水题,就是让你求Cnk

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1000010
#define mod 1000000007
using namespace std;
int f[MAXN];
int pow(int a,int b){
    int ret=1%mod;
    while(b){
        if(b&1) ret=ret*1LL*a%mod;
        b>>=1;
        a=a*1LL*a%mod;
    }
    return ret;
}
int ni(int x){
    return pow(x,mod-2);
}
int C(int n,int m){
    if(m>n) return 0;
    return f[n]*1LL*ni(f[m])%mod*ni(f[n-m])%mod;
}
int main(){
    freopen("cube.in","r",stdin);
    freopen("cube.out","w",stdout);
    f[0]=1;
    int n,k;
    for(int i=1;i<=1000000;i++)    f[i]=f[i-1]*1LL*i%mod;
    scanf("%d%d",&n,&k);
    for(int p,i=1;i<=n;i++)    scanf("%d",&p);
    cout<<C(n,k);
    return 0;
}

思路:跑一遍最大生成树。因为要达到最优的话,走的路径一定是最大生成树上的。

然后对于每次查询,二分答案去找小于k的数的个数。因为对于一棵树,有几条小于k的边,他就会被分割为k+1块。所以我们只要查询小于k的数的个数+1即为答案。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,m,q,w,num;
int vis[MAXN],fa[MAXN],sum[MAXN];
struct nond{
    int x,y,z;
}edge[MAXN];
int cmp(nond a,nond b){
    return a.z>b.z;
}
int find(int k){
    if(fa[k]==k)    return fa[k];
    else return fa[k]=find(fa[k]);
}
int main(){
    freopen("warehouse.in","r",stdin);
    freopen("warehouse.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
    sort(edge+1,edge+1+m,cmp);
    for(int i=1;i<=n;i++)    fa[i]=i;
    for(int i=1;i<=m;i++){
        int dx=find(edge[i].x);
        int dy=find(edge[i].y);
        if(dx==dy)    continue ;
        fa[dy]=dx;
        num++;sum[num]=edge[i].z;
        if(num==n-1)    break;
    }
    sort(sum+1,sum+1+n-1);
    for(int i=1;i<=q;i++){
        scanf("%d",&w);
        int l=1,r=n-1;
        while(l<=r){
            int mid=(l+r)/2;
            if(sum[mid]<w)    l=mid+1;
            else r=mid-1;
        }
        cout<<l<<endl;
    }
    return 0;
}

 

 

posted @ 2017-11-05 22:10  一蓑烟雨任生平  阅读(188)  评论(0编辑  收藏  举报