N校联考 D2
来源:互联网 发布:桌面录制视频软件 编辑:程序博客网 时间:2024/05/17 06:31
今天开头就写着几个大字
信心题
浅览题目 好像都不会诶
我肯定是打开方式不对 于是我又重新开了一遍
发现依旧不会做 于是乱搞
1.祖孙询问
【问题描述】
已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。
【输入格式】
输入第一行包括一个整数n表示节点个数。
接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。
第n+2行是一个整数m表示询问个数。
接下来m行,每行两个正整数x和y。
【输出格式】
对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0。
【样例输入】
10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19
【样例输出】
1
0
0
0
2
【数据规模】
对于30%的数据,n,m≤1000。
对于100%的.据,n,m≤40000,每个节点的编号都不超过40000。
恩 对于树结构的东西我一般都不怎么会
一看 好的 暴力还是可以的
然后想想 其实dfs 一下处理记录处理的顺序 然后就有一些规律了
void dfs(int x){ timein[x] =cur++; for(int i=head[x]; i!=-1 ;i=e[i].next){ if(timein[e[i].v]==0) { dfs(e[i].v); } } timeout[x] = cur++;}for(int i=1 ;i<=m ;i++) { int x=read(),y=read(); if(x==-1){printf("1\n");continue;} if(y==-1){printf("2\n");continue;} if(timein[x] < timein[y] && timeout[x] >timeout[y]){printf("1\n");continue;} if(timein[x] > timein[y] && timeout[x] <timeout[y]){printf("2\n");continue;} printf("0\n"); }
以上就是我的大致思路。。。
其实我觉得应该可以过的
但没有 其实dfs 可以改一下的
当然这是很明显的LCA问题了
但我不会 或者说 记不得
然后重新看了看
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int n,m,zz,head[40002],root;struct bian{int to,nx;} e[80002];int fa[40002][20],h[40002];//2^16=65536void insert(int x,int y){ zz++; e[zz].to=y; e[zz].nx=head[x]; head[x]=zz; zz++; e[zz].to=x; e[zz].nx=head[y]; head[y]=zz;}void init(){ int i,x,y; scanf("%d",&n); for(i=1;i<=n;i++) {scanf("%d%d",&x,&y); if(y==-1) root=x; else insert(x,y); }}void dfs(int x){ int i,p; for(i=1;i<=15;i++) {if(h[x]<(1<<i)) break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for(i=head[x];i;i=e[i].nx) {p=e[i].to; if(p==fa[x][0]) continue; h[p]=h[x]+1; fa[p][0]=x; dfs(p); }}int lca(int x,int y){ if(h[x]<h[y]) swap(x,y); int i,c; c=h[x]-h[y]; for(i=15;i>=0;i--) {if(c&(1<<i)) x=fa[x][i];} for(i=15;i>=0;i--) {if(fa[x][i]!=fa[y][i]) {x=fa[x][i]; y=fa[y][i];} } if(x==y) return x; else return fa[x][0];}void work(){ int i,x,y,t; scanf("%d",&m); dfs(root); for(i=1;i<=m;i++) {scanf("%d%d",&x,&y); if(x==y) printf("0\n"); else {t=lca(x,y); if(t==x) printf("1\n"); else if(t==y) printf("2\n"); else printf("0\n"); } }}int main(){ .......}
dfs 好像可以 如果担心爆就bfs吧
2.比赛
【问题描述】
有两个队伍A和B,每个队伍都有n个人。这两支队伍之间进行n场1对1比赛,每一场都是由A中的一个选手与B中的一个选手对抗。同一个人不会参加多场比赛,每个人的对手都是随机而等概率的。例如A队有A1和A2两个人,B队有B1和B2两个人,那么(A1 vs B1,A2 vs B2)和(A1 vs B2,A2 vs B1)的概率都是均等的50%。
每个选手都有一个非负的实力值。如果实力值为X和Y的选手对抗,那么实力值较强的选手所在的队伍将会获得(X-Y)^2的得分。
求A的得分减B的得分的期望值。
【输入格式】
第一行一个数n表示两队的人数为n。
第二行n个数,第i个数A[i]表示队伍A的第i个人的实力值。
第三行n个数,第i个数B[i]表示队伍B的第i个人的实力值。
【输出格式】
输出仅包含一个实数表示A期望赢B多少分。答案保留到小数点后一位(注意精度)。
【样例输入】
2
3 7
1 5
【样例输出】
20.0
【数据规模】
对于30%的数据,n≤50。
对于100%的.据,n≤50000;A[i],B[i]≤50000。
恩
我坚信暴力一定都会
然后排序再暴力一定可以优化
然后其实排序之后拿个指针记录就可以线性完成
我们算A的所以把B给预处理了
S【】记前缀和 SQ【】记前缀平方和 (*long long 很重要)
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;inline int read(){ // int int x=0,f=1;char ch=getchar(); while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void init(){ freopen("mat.in","r",stdin); freopen("mat.out","w",stdout);}int n;int a[50005],b[50005];double ans = 0.0;long long s[50005],sq[50005];inline long long sqr(long long x){ return x*x;}void readdata(){ n=read(); for(int i=1 ;i<=n ;i++) a[i]=read();// A power-range for(int i=1 ;i<=n ;i++) b[i]=read();// B power-range //have a sort to get up-arr sort(a+1 ,a+n+1); sort(b+1 ,b+n+1); for(int i=1 ;i<=n ;i++) //维护前缀 { sq[i] = sqr(b[i]) + sq[i-1]; // b[i]^2 s[i] = b[i] + s[i-1]; // b[i] }}// liner-work() void work(){ int L=0;// L+1 double tem = 0.0; for(int i=1 ;i<=n ;i++) // enumeration { tem = 0.0; while(L<n && a[i] > b[L+1])// { L++; } //二次项展开合并 tem += L * sqr(a[i]) - 2 * s[L] * a[i] + sq[L]; tem -= (n - L) * sqr(a[i]) - 2 * (s[n] - s[L]) *a[i] + (sq[n] - sq[L]); tem /= n; ans+=tem; }} int main(){ init(); readdata(); work(); printf("%.1lf",ans); }
(那些无聊的注释直接无视)
3.数字
【问题描述】
一个数字被称为好数字当他满足下列条件:
1. 它有2*n个数位,n是正整数(允许有前导0)。
2. 构成它的每个数字都在给定的数字集合S中。
3. 它前n位之和与后n位之和相等或者它奇数位之和与偶数位之和相等
例如对于n=2,S={1,2},合法的好数字有1111,1122,1212,1221,2112,2121,2211,2222这样8种。
已知n,求合法的好数字的个数mod 999983。
【输入格式】
第一行一个数n。
接下来一个长度不超过10的字符串,表示给定的数字集合。
【输出格式】
一行一个数字表示合法的好数字的个数mod 999983。
【样例输入】
2
0987654321
【样例输出】
1240
【数据规模】
对于20%的数据,n≤7。
对于100%的.据,n≤1000,|S|≤10。
题解:
ANS=前n位之和与后n位之和相等的方案数+奇数位之和与偶数位之和相等的方案数-前n位之和与后n位之和相等且奇数位之和与偶数位之和相等的方案数
前2个需要+的方案数都很好求,直接递推,重点是最后一个要满足2个条件的方案数怎么求,其实也很简单:
因为前n位之和=后n位之和,奇数位之和=偶数位之和
所以前n位中奇数位之和=后n位中偶数位之和 且
前n位中偶数位之和=后n位中奇数位之和
现在只要求上面这个问题的方案数,由于两个等式中的元素无交集,也是十分好算的。
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#define mod 999983#define ll long longusing namespace std;inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}int n;char ch[15];int a[15];int f[1005][9005];ll ans;ll cal(int x){ ll ans=0; for(int i=0;i<=x*9;i++) if(f[x][i]) ans=(ans+((ll)f[x][i]*f[x][i]))%mod; return ans;}int main(){ //freopen("num.in","r",stdin); //freopen("num.out","w",stdout); n=read(); scanf("%s",ch); int l=strlen(ch); for(int i=0;i<l;i++) a[i+1]=ch[i]-'0'; f[0][0]=1; for(int i=0;i<n;i++) for(int j=0;j<=n*9;j++) if(f[i][j]) for(int k=1;k<=l;k++) f[i+1][j+a[k]]=(f[i+1][j+a[k]]+f[i][j])%mod; ans=2*cal(n)-cal(n/2)*cal(n-n/2); printf("%d",(ans%mod+mod)%mod); return 0;}
- N校联考 D2
- <MZ&DC联考>D2 T1
- <MZ&DC联考>D2 T2
- <MZ & DC 联考>D2 T3
- 高端的N 校联考题
- D2
- D2
- d2
- 关于五校联考
- 【五校联考】集体照
- 11.7多校联考
- 【八校联考2013】军训
- 五校联考四总结
- 五校联考4总结
- 【五校联考四】总结
- 五校联考六T1
- 五校联考六T2
- 五校联考六T3
- mysql中如何设置默认时间为当前时间
- 使用蒲公英来做iOS测试应用的分发
- 第二章 安卓基础学习
- 【UKIEPC2015 C】【STL set map stringstream】Conversation Log 网络审查 被所有人都说过的话 map套set法+人哈希法
- Button中使用颜色控制按钮点击时的形状和颜色
- N校联考 D2
- Apache与Tomcat整合
- CSR8615蓝牙芯片功能调试入门笔记------ 下
- 仿淘宝的继续拖动显示详情页面
- Oracle模糊查询时间以及按照时间区间查询+补充mysql
- android adt23.0.6的文件打包混淆时遇到的问题
- 深入理解JDBC的超时设置
- 【UKIEPC2015 J】【趣味迷宫搜索】Jelly Raid 来回巡逻 不被发觉 循环节预处理
- ConcurrentHashMap 原理详解