文章目录
cf697B. Barnicle(科学计数法转正常小数 模拟)
cf697B. Barnicle(科学计数法转正常小数 模拟)
题意
科学计数法转化为正常的小数,a.deb输入保证d没有前导0(但d可以是0) a是0的话 b一定是0.
代码
#include<bits/stdc++.h>
using namespace std;
const int N=200+10;
char s[N];int x[N],y[N],z[N];
int main(){
scanf("%s",s+1);int n=strlen(s+1);
int C=0,lenc=0,flag=0;
for(int i=1;i<=n;++i){
if(!flag){
if(s[i]=='e') flag=1;
continue;
}else C+=s[i]-'0',C*=10,++lenc;
}
C/=10;
int numx=0,numy=0,numz=0,flag1=0,flag2=0;//flag1是小数点前最先不是1的在numx数组的下标。
x[++numx]=s[1]-'0';
if(x[numx]) flag1=numx;
for(int i=3;i<=3+C-1;++i){//小数点前面
if(i>=n-lenc) x[++numx]=0;//多补的0
else x[++numx]=s[i]-'0';
if(!flag1&&x[numx]) flag1=numx;
}
for(int i=3+C;i<=n-lenc-1;++i){//小数点后面
y[++numy]=s[i]-'0';
if(!flag2&&y[numy]) flag2=numy;
}
if(!flag1) cout<<0;
else for(int i=flag1;i<=numx;++i) cout<<x[i];//去掉前导0
if(!flag2) return 0;
cout<<'.';
for(int i=1;i<=numy;++i) cout<<y[i];//不需要去掉后导0因为输入的b没有后导0
}
cf697C. Lorenzo Von Matterhorn(超大线段树两点间的LCA)
cf697C. Lorenzo Von Matterhorn(超大线段树两点间的LCA)
题意
在一棵树中有操作 1 u v w :将u v路径上的边权值加w
询问 2 u v :u v路径上的权值和。
这棵树是线段树的构造。q次询问(q<=1000 但是 点<=1e18)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>mp;
ll LCA(ll u,ll v,ll w){
ll ans=0;
while(u!=v){
if(u<v) swap(u,v);
mp[u]+=w,ans+=mp[u];
u>>=1;
}
return ans;
}
int main(){
int q;scanf("%d",&q);
while(q--){
ll f,u,v,w;cin>>f>>u>>v;
if(f==1) cin>>w,LCA(u,v,w);
else cout<<LCA(u,v,0)<<endl;
}
}
cf697D. Puzzles(树上dfs序遍历每个点编号的期望)
cf697D. Puzzles(树上dfs序遍历每个点编号的期望)
题意:
每个点访问他的儿子没有顺序。有好多dfs序。问树上每个点的dfs序标号的期望值。
思路
这个节点要么排在兄弟节点之前要么之后就是:
dp[y]=dp[x]+0.5*1+0.5 * (sz[x]-sz[y]-1 +1).
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct Edge{int to,nex;}edge[N];
int head[N],tot;
inline void add(int from,int to){edge[++tot]=(Edge){to,head[from]},head[from]=tot;}
double dp[N];int sz[N];
void dfs1(int x){
sz[x]=1;
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to;
dfs1(y),sz[x]+=sz[y];
}
}
void dfs2(int x){
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to;
dp[y]=dp[x]+1+(sz[x]-sz[y]-1)*0.5;
dfs2(y);
}
}
int main(){
int n;scanf("%d",&n);
for(int i=2,fa;i<=n;++i) scanf("%d",&fa),add(fa,i);
dp[1]=1;
dfs1(1),dfs2(1);
for(int i=1;i<=n;++i) printf("%.7f ",dp[i]);
}
cf697E. PLEASE(简单概率+基础数论知识)
题意
有三个杯子都倒放在桌面上,中间的杯子里有筛子,每一次都把中间的杯子与左右两边的杯子等概论交换,问交换n后,筛子还在中间的杯子里的概率,对该式子约分之后 分母分子分别%1e9+7 输出分子分母。
n非常大,给你k个数,n就是这k个数的乘积。
思路
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,phimod=mod-1;//phimod是mod的欧拉值
typedef long long ll;
ll quick_mod(ll c,ll p,ll mod){
ll res=1;
while(p){
if(p&1) res=res*c%mod;
c=c*c%mod,p>>=1;
}
return res;
}
int main(){
int n;scanf("%d",&n);
ll mi=1,jo=0;int num=0;
for(int i=1;i<=n;++i){
ll x;scanf("%lld",&x);
if(!(x&1)) ++num;//判断n的奇偶
x=x%phimod,mi=mi*x%phimod;//欧拉降幂求指数
}
mi=(mi+phimod-1)%phimod;//求的是2^n 应该是2^(n-1)
ll inv3=quick_mod(3,mod-2,mod),p,q;//3关于1e9+7的逆元
p=quick_mod(2,mi,mod),q=p;//p q分别为分子分母
(!num)?(p-=1):(p+=1);
p=(p+mod)%mod*inv3%mod;//由于p可能-1 所以p+mod.
printf("%lld/%lld\n",p,q);
}