T1三向城
只有我是60pts
画一下 (7) 个点的图会发现这是颗二叉树,找两个点的最短路径就是找 (LCA),当没找到 (LCA) 的时候就让两个数中大的一个除以 (2),对于 (10^9) 他的深度不超过 (30) 所以一次暴跳找 (LCA) 不超过 (60) 次,询问只有 (10^4) 可以过。
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
inline void read(int &T) {
int x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
T=f?-x:x;
}
int n,x,y;
int main() {
read(n);
for(int i=1,ans=0;i<=n;++i) {
read(x),read(y);
while(x!=y) {
if(x<y) y/=2;
else x/=2;
++ans;
}
std::cout<<ans<<'
';
ans=0;
}
return 0;
}
T2灵魂画师
期望dp。因为每个画纸初始颜色都一样,所以我们只对一张画纸求概率即可。设dp[i][j]为一张画纸经过 (i) 次操作变成了颜色 (j) 的概率。因为集合中每个元素不被选中的概率为 (frac{1}{2}),所以dp[i][j]+=dp[i-1][j]/2。因为每个颜色被选中的概率率为 (frac{1}{c}),所以dp[i][j * k%c]+=dp[i][j]/2c(选中了第k种颜色)。期望就等于dp[i][j] * j,因为和的期望等于期望的和,所以最后把期望加一下就是答案。
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<iomanip>
inline void read(int &T) {
int x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
T=f?-x:x;
}
int n,k,c,maxn,cnt[101];
double dp[101][101];
int max(int a,int b) {
return a>b?a:b;
}
int main() {
read(n),read(c),read(k);
for(int i=1,l,r;i<=k;++i) {
read(l),read(r);
for(int j=l;j<=r;++j) {
++cnt[j];
maxn=max(maxn,cnt[j]);
}
}
dp[0][1]=1;
for(int i=1;i<=maxn;++i) {
for(int j=0;j<c;++j) {
for(int k=0;k<c;++k) {
dp[i][j*k%c]+=dp[i-1][j]/(2*c);
}
dp[i][j]+=dp[i-1][j]/2;
}
}
double ans=0;
for(int i=1;i<=n;++i) {
for(int j=0;j<c;++j) {
ans+=dp[cnt[i]][j]*j;
}
}
std::cout<<std::fixed<<std::setprecision(3)<<ans<<'
';
return 0;
}