练习赛
一、题目概览
中文题目名称 |
树 |
红与蓝 |
猜数列 |
英文题目名称 |
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; }
红与蓝(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。