T1: WJMZBMR打osu! / Easy
其实应该是 WJMZBMR打osu! / Difficult
传送门:P1365 WJMZBMR打osu! / Easy
算法分析:
又是万恶的DP啊!
定义一个
l
e
n
[
i
]
len[i]
len[i] 来存储到第
i
i
i 个字符时 ‘o’ 连续个数的期望,
f
[
i
]
f[i]
f[i] 代表到第
i
i
i 个字符时的期望得分,然后分类讨论:
- 当
a
[
i
]
=
a[i]=
a[i]=‘x’ 时:
l e n [ i ] = l e n [ i − 1 ] + 1 len[i]=len[i-1]+1 len[i]=len[i−1]+1
f [ i ] = f [ i − 1 ] + ( l e n [ i ] 2 − l e n [ i − 1 ] 2 ) f[i]=f[i-1]+(len[i]^2-len[i-1]^2) f[i]=f[i−1]+(len[i]2−len[i−1]2)
= f [ i − 1 ] + ( l e n [ i ] 2 − ( l e n [ i ] − 1 ) 2 ) \ \ \ \ \ \ \ =f[i-1]+\bigg(len[i]^2-(len[i]-1)^2\bigg) =f[i−1]+(len[i]2−(len[i]−1)2)
= f [ i − 1 ] + ( 2 × l e n [ i ] − 1 ) \ \ \ \ \ \ \ =f[i-1]+(2×len[i]-1) =f[i−1]+(2×len[i]−1) - 当
a
[
i
]
=
a[i]=
a[i]=‘o’ 时
l e n [ i ] = 0 len[i]=0 len[i]=0
f [ i ] = f [ i − 1 ] f[i]=f[i-1] f[i]=f[i−1] - 当
a
[
i
]
=
a[i]=
a[i]=‘
?
?
?’ 时有点难处理,不过由于这时有
50
%
50\%
50% 的几率为 ‘x’ ,有
50
%
50\%
50% 的几率为 ‘o’ 那就用
a
[
i
]
=
′
x
′
a[i]= 'x'
a[i]=′x′ 与
a
[
i
]
=
′
o
′
a[i]='o'
a[i]=′o′ 时的概率相加除以
2
2
2 即可
l e n [ i ] = l e n [ i − 1 ] + 1 2 len[i]=\frac{len[i-1]+1}{2} len[i]=2len[i−1]+1
f [ i ] = f [ i − 1 ] + l e n [ i ] − 1 2 f[i]=f[i-1]+len[i]-\frac{1}{2} f[i]=f[i−1]+len[i]−21
Code:
#include<bits/stdc++.h>
using namespace std;
inline int Read(){int dx=0,fh=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') fh=-1;c=getchar();}while(c>='0'&&c<='9'){dx=dx*10+c-'0';c=getchar();}return fh*dx;}
int n;
double f[300005],len[300005];
int main(){
n=Read();
for(int i=1;i<=n;++i){
char c=getchar();
if(c=='o'){
len[i]=len[i-1]+1;
f[i]=f[i-1]+2*len[i-1]+1;
}
if(c=='x'){
len[i]=0;
f[i]=f[i-1];
}
if(c=='?'){
len[i]=(len[i-1]+1)/2;
f[i]=f[i-1]+len[i-1]+0.5;
}
}
if(fabs(f[n])<=1e-8) {
printf("0.0000");
}
else printf("%.4lf",f[n]);
return 0;
}
反思与总结:
- C++11最好不要用long double
- 要注意 − 0.000 -0.000 −0.000 的处理
T2:百事世界杯之旅
传送门:P1291 [SHOI2002]百事世界杯之旅
百事和CCF之间一定有py交易
算法分析: 是否集齐卡牌和卡牌的顺序无关,所以需要的可乐数量为
n
×
∏
i
=
1
n
1
i
n×\displaystyle\prod_{i=1}^n\frac{1}{i}
n×i=1∏ni1
分数的输出很毒瘤,要认真写.
Code:
#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
inline ll Read(){ll dx=0,fh=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') fh=-1;c=getchar();}while(c>='0'&&c<='9'){dx=dx*10+c-'0';c=getchar();}return fh*dx;}
struct fraction{ll son,mother,dai;};
ll gcd(ll x,ll y){if(x==0) return y;return gcd(y%x,x);}
void easien(fraction &x){
ll Gcd=gcd(x.son,x.mother);
x.son/=Gcd;
x.mother/=Gcd;
}
ll Count(ll x){
ll cnt=0;
if(x==0) return 1;
while(x){
++cnt;
x/=10;
}
return cnt;
}
fraction Add(fraction x,fraction y){
easien(x),easien(y);
ll lcm=x.mother/gcd(x.mother,y.mother)*y.mother;
fraction Return;
easien(x),easien(y);
Return.mother=lcm;
ll xx=lcm/x.mother,yy=lcm/y.mother;
Return.son=x.son*xx+y.son*yy;
easien(x);easien(y);
return Return;
}
void out_put(fraction &x){
easien(x);
x.dai=x.son/x.mother;
x.son=x.son%x.mother;
if(x.son==0){
printf("%llu\n\n",x.dai);
return;
}
ll Space=Count(x.dai);
if(x.dai!=0) for(ll i=1;i<=Space;++i) putchar(' ');
printf("%llu\n",x.son);
if(x.dai!=0) printf("%llu",x.dai);
for(ll i=1;i<=Count(x.mother);++i) putchar('-');putchar('\n');
if(x.dai!=0) for(ll i=1;i<=Space;++i) putchar(' ');
printf("%llu\n\n",x.mother);
}
ll n;
fraction m;
int main(){
n=Read();
m.mother=1;
m.son=0;easien(m);
for(ll i=1;i<=n;++i){easien(m);
fraction a;
a.son=1;easien(m);
a.mother=i;
m=Add(m,a);easien(m);
easien(m); easien(m);
}
m.son*=n;
easien(m);
out_put(m);
return 0;
}
反思与总结:
四年OI一场空
先乘后除见祖宗