目前水平有限,补了四题。。。
感觉这场质量很高,没有白补。
A. Pineapple Incident
题意&思路:水题
#include<bits/stdc++.h>
using namespace std;
int main(){
int t,s,x;
while(cin>>t>>s>>x){
if(x==t||(x-t)%s==0&&x>t||(x-t-1)%s==0&&(x-t-1>0)) printf("YES\n");
else printf("NO\n");
}
}
B. Barnicle
题意&思路:字符串模拟一下科学计数法转换,注意下细节。
这几个数据容易错:
8.77056e6
7.0e100
1.0e0
0.0e10
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
while(cin>>s){
int nz=0,a,e,b=0,ok=0;
a=s[0]-'0';
for(int i=2;i<s.size();i++){
if(s[i]=='e') { e=i;ok=1;}
else if(!ok&&s[i]>='1'&&s[i]<='9') nz=i;
else if(ok) b=b*10+s[i]-'0';
}
ok=0;
if(a||b==0) { cout<<a;ok=1;}
if(b>=nz-1){
for(int i=2;i<=nz;i++){
if(ok||s[i]!='0') cout<<s[i],ok=1;
}
if(nz==0) nz=1;
for(int i=0;i<b-nz+1;i++) cout<<0;
cout<<endl;
}
else{
for(int i=2;i<b+2;i++){
if(ok||s[i]!='0') cout<<s[i],ok=1;
}
cout<<".";
for(int i=b+2;i<=nz;i++) cout<<s[i];
cout<<endl;
}
}
}
C. Lorenzo Von Matterhorn
题意:在一棵根为1的二叉搜索树上(每个点的子孙是他的两倍和两倍+1),在这个树上更新任意两点之间的边的权值,和询问树上任意两点之间边之和。
思路:在一棵二叉搜索树上,边之间点都是2^n增加,所以直接暴力复杂度O(logn),范围10^18,
就用map。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>m;
int main(){
int q;cin>>q;
m.clear();
while(q--){
ll o,u,v;cin>>o>>u>>v;
if(o==1){
ll w;cin>>w;
while(u!=v){
if(u>v) swap(u,v);
m[v]+=w;
v/=2;
}
}
else{
ll ans=0;
while(u!=v){
if(u>v) swap(u,v);
ans+=m[v];
v/=2;
}
cout<<ans<<endl;
}
}
}
D.Puzzles
题意:给你一棵树,然后让你从1点dfs,但是dfs的时候如果有多个结点,那么则随机选一个结点去访问,最后问你每个点访问时间的期望,假设访问一个结点用时1s。
思路:
分析一颗子树:
当前已知节点1的期望为1.0 ->anw[1]=1.0
需要通过节点1递推出节点2、4、5的期望值
1的儿子分别是2、4、5,那么dfs序所有可能的排列是6种:
1:1-2-4-5 (2、4、5节点的儿子没有写出)
2:1-2-5-4
3:1-4-2-5
4:1-4-5-2
5:1-5-2-4
6:1-5-4-2
这六种情况分别:
都有一部分:2都是从1转移过来,首先共有ans[1]+1;
第二部分:当节点1到达节点2的时候贡献是0,种类分别对应(1、2)
当先到达节点4后到节点2的时候贡献(size(4)+size(4)+szie(5)),种类分别对应(3、4)
当先到达节点5后到节点2的时候贡献(size(5)+size(5)+size(4)),种类分别对应(5、6)
而所有的排列对于的概率都是1/6,所以第二部分的贡献就是(0+size(4)*3+size(5)*3)/6 = (size(4)+size(5))/2=(size(1)-size(6)-1)/2
多找几棵子树就可以发现 对于第二部分求法有推导: ans[v]=(size(u)-size(v)-1)/2
可以这样理解:对于v点,当走到他的父亲u点时,它可以选择最优一步到v,即贡献为0,也可以最差,走完u点其他所有点后最后到v,即贡献度为size[u]-size[v]-1;
#include<bits/stdc++.h>
using namespace std;
template<int N,int M>//N点的个数,M边的个数
struct Graph
{
int top;
struct Vertex{
int head;
}V[N];
struct Edge{
int v,next;
}E[M];
void init(){
memset(V,-1,sizeof(V));
top = 0;
}
void add_edge(int u,int v){
E[top].v = v;
E[top].next = V[u].head;
V[u].head = top++;
}
};
Graph<100000+10,100000*2+10> g;
int sum[100000+10];
double ans[100000+10];
void dfs1(int u,int f){
sum[u]=1;
for(int i=g.V[u].head;i!=-1;i=g.E[i].next){
int v=g.E[i].v;
if(v==f) continue;
dfs1(v,u);
sum[u]+=sum[v];
}
}
void dfs2(int u,int f){
for(int i=g.V[u].head;i!=-1;i=g.E[i].next){
int v=g.E[i].v;
if(v==f) continue;
ans[v]=ans[u]+1.0+(sum[u]-sum[v]-1)*0.5;
dfs2(v,u);
}
}
int main(){
int n;
while(~scanf("%d",&n)){
g.init();
memset(sum,0,sizeof(sum));
for(int i=2;i<=n;i++){
int x;scanf("%d",&x);
g.add_edge(x,i);
g.add_edge(i,x);
}
memset(ans,0,sizeof(ans));
dfs1(1,-1);
ans[1]=1.0;
dfs2(1,-1);
for(int i=1;i<n;i++) printf("%.2f ",ans[i]);
printf("%.2f\n",ans[n]);
}
}