湖南雅礼培训 1.1

练习赛

一、题目概览

中文题目名称

红与蓝

猜数列

英文题目名称

tree

rab

hidden

可执行文件名

tree

rab

hidden

输入文件名

tree.in

rab.in

hidden.in

输出文件名

tree.out

rab.out

hidden.out

时间限制

1s

1s

1s

空间限制

256MB

256MB

256MB

测试点数目

10

10

25

测试点分值

10

10

4

题目类型

传统

传统

传统

比较方式

全文比较

spj

全文比较

是否有部分分

 

 

 

二、注意事项:

1.文件名(程序名和输入输出文件名)必须使用小写。

2.C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。

3.开启O2优化,栈空间开大至256M。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

树(tree)

【题目描述】

    有n个点,第i个点的限制为度数不能超过ai。

    现在对于每一个s(1<=s<=n),问从这n个点中选出s个点组成有标号无根树的方案数。

【输入数据】

       第一行一个整数表示n。

       第二行n个整数a1~an。

【输出数据】

一个n个整数,第i个整数表示s=i时的答案。

答案模1004535809

【样例输入】

3

2 2 1

【样例输出】

       3 3 2

【数据范围】

       对于20%的数据,n≤6。

对于60%的数据,n≤50。

对于100%的数据,n≤100。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 101
#define mod 1004535809
using namespace std;
int n,a[maxn],ans[maxn],t[maxn],num,b[maxn];
bool vis[maxn];
void dfs2(int pos){
    if(pos==num-1){
        ans[num]++;
        if(ans[num]>=mod)ans[num]-=mod;
        return;
    }
    for(int i=1;i<=num;i++){
        int ii=b[i];
        if(t[ii]!=a[ii]-1){
            t[ii]++;
            dfs2(pos+1);
            t[ii]--;
        }
    }
}
void dfs1(int pos,int id){
    if(pos==n+1){
        return;
    }
    for(int i=id;i<=n;i++){
        if(!vis[i]){
            b[pos]=i;
            vis[i]=1;
            if(pos>=3)num=pos,dfs2(1);
            dfs1(pos+1,i+1);
            vis[i]=0;
        }
    }
}
int main(){
//    freopen("Cola.txt","r",stdin);
    freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(int i=n;i>=1;i--){
        if(a[i]>n-1)a[i]=n-1;
        else break;
    }
    ans[1]=n;ans[2]=(n-1)*n/2;
    dfs1(1,1);
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    return 0;
}
暴力
#include<iostream>
#include<cstdio>
#define maxn 101
#define mod 1004535809
int n,m,ans,f[maxn][maxn][maxn*2],a[maxn],c[maxn*2][maxn];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i]=min(a[i],n);a[i]--;
    }
    c[0][0]=1;
    for(int i=1;i<=n;i++){
        c[i][0]=1;
        for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
    }
    f[0][0][0]=1;//到第i个点,选了j个点,purfer数列中有k个点的方案数 
    for(int i=0;i<n;i++)
        for(int k=0;k<n;k++)
            for(int j=0;j<=n;j++)
                if(f[i][k][j]){
                    f[i+1][k][j]=(f[i+1][k][j]+f[i][k][j])%mod;
                    for(int t=0;t<=a[i+1];t++)(f[i+1][k+1][j+t]+=1LL*f[i][k][j]*c[j+t][t]%mod)%=mod;
                }
    for(int k=1;k<=n;j++){
        if(k==1)ans=n;
        else ans=f[n][k][k-2];
        ans=(ans+mod)%mod;
        printf("%d ",ans);
    }
    return 0;
}
100分 purfer数列dp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

红与蓝(rab)

【题目描述】

    给定一棵树,初始时非叶节点均为无色,叶节点会是红色、蓝色或无色。

       小红和小蓝轮流给无色叶子染色(小红染红色,小蓝染蓝色,小红先染)。所有叶子染完后,非叶节点的颜色将被逐一确定:一个非叶节点的颜色是它所有儿子的颜色中出现较多的那个(保证有奇数个儿子)。最后,根是谁的颜色谁就获胜。

       求小红是否能赢,若能赢,求出第一步选择哪些叶子能赢。

【输入数据】

       第一行一个整数t表示数据组数。

       每组数据第一行一个整数n表示节点数。

第二行n个整数,第i个整数fi表示i的父亲,保证f1=0。

第三行n个整数,第i个整数gi表示i的初始颜色(0表示红色,1表示蓝色,-1表示无色)。

【输出数据】

每组数据输出一行。

若小红能赢,先输出一个整数m表示第一步可以选的叶子数,接下来m个整数表示那些叶子的编号,从小到大输出。若你只知道小红能赢,你可以只输出一行一个整数0。

否则输出一个整数-1。

【样例输入】

2

2

0 1

-1 -1

2

0 1

-1 1

【样例输出】

       1 2

       -1

【数据范围】

       对于20%的数据,t=1,n≤20。

对于60%的数据,n≤2000。

对于100%的数据,t<=10,n≤100000。

若你只判断对了胜负,可以获得该测试点一半的分数。

 

 

 

 

 

 

 

 

猜数列(hidden)

【题目描述】

有一个长度为m的,由1到9之间的数构成的未知数列a。

你现在有n个线索,每个线索都是用如下方式生成的:

(1)选择序列a的某一个位置p作为开始;

(2)选择某个方向(向左或向右);

(3)从p出发往你选择的方向走,每遇到一个之前未出现的数就将它加到线索中。

现在你需要求出满足所有线索的长度最小的序列的长度。

【输入数据】

输入文件的第一行为一个整数n,表示线索的数量。

接下来n行,每行有若干个以0结尾的整数,表示一条线索。保证一条线索中的数在[1,9]中且不会出现相同的数。

【输出数据】

如果无解请输出-1,否则输出可能的最小长度。

【样例输入1

       5

1 2 0

3 4 0

1 4 3 0

3 1 4 2 0

1 2 4 3 0

【样例输出1

       7

【样例输入2

3
1 2 0
2 3 0
3 4 0

【样例输出2

       -1

【数据范围】

对于20%的数据,答案不超过10。

对于另外40%的数据,保证存在一个最优解,使得所有线索都可以通过向右遍历得到。

对于100%的数据,1≤n≤10。

转载于:https://www.cnblogs.com/thmyl/p/8167958.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值