A,B,D,F看下面:
https://blog.csdn.net/Myriad_Dreamin/article/details/79209441
C看这里:
https://blog.csdn.net/Myriad_Dreamin/article/details/79349060
CodeForces - 697D - E - Puzzle
我们知道期望拥有线性性,所以假设
i
i
i是待求顶点,
p
r
e
pre
pre是父亲数组,
s
i
z
siz
siz是以
i
i
i为根的子树的顶点个数,
n
u
m
num
num表示
i
i
i的孩子的个数,
s
o
n
[
i
]
son[i]
son[i]表示
i
i
i的孩子顶点,那么:
E
(
i
)
=
1
+
E
(
p
r
e
[
i
]
)
+
∑
k
=
0
n
u
m
[
p
r
e
[
k
]
]
∑
J
⊂
Ω
n
\
{
i
}
,
∣
J
∣
=
k
∑
j
∈
J
s
i
z
[
s
o
n
[
p
r
e
[
k
]
]
[
j
]
]
n
u
m
[
p
r
e
[
i
]
]
!
=
1
+
E
(
p
r
e
[
i
]
)
+
1
n
u
m
[
p
r
e
[
i
]
]
!
(
n
u
m
[
p
r
e
[
i
]
]
!
2
(
s
i
z
[
p
r
e
[
i
]
]
−
s
i
z
[
i
]
−
1
)
)
=
E
[
p
r
e
[
i
]
]
+
s
i
z
[
p
r
e
[
i
]
]
−
s
i
z
[
i
]
+
1
2
\begin{array}{rl} E(i)=&\displaystyle 1+E(pre[i])+\frac{\displaystyle \sum_{k=0}^{num[pre[k]]}\sum_{J\subset \Omega_n\backslash \{i\},|J|=k}\sum_{j\in J}siz[son[pre[k]][j]]}{num[pre[i]]!} \\=&1+E(pre[i])+\displaystyle \frac{1}{num[pre[i]]!}\left(\frac{num[pre[i]]!}{2}(siz[pre[i]]-siz[i]-1)\right) \\=&E[pre[i]]+\displaystyle \frac{siz[pre[i]]-siz[i]+1}{2} \end{array}
E(i)===1+E(pre[i])+num[pre[i]]!k=0∑num[pre[k]]J⊂Ωn\{i},∣J∣=k∑j∈J∑siz[son[pre[k]][j]]1+E(pre[i])+num[pre[i]]!1(2num[pre[i]]!(siz[pre[i]]−siz[i]−1))E[pre[i]]+2siz[pre[i]]−siz[i]+1
可能狠多人都是找规律的,这里不多加证明,而是给出一个很直观的想法:将子树捆绑在一起,它出现在每个位置的概率等同,而总的期望是长度的均值.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=100005,M=200005;
int pre[N],deg[N],siz[N];
const int Headsize=N,Edgesize=M;
int head[Headsize+5],mal;
struct edge{
int nx,to;
}e[Edgesize+5];
inline void init(){
mal=1;
memset(head,0,sizeof(head));
}
inline void addedge(int u,int v){
e[mal].to=v;e[mal].nx=head[u];head[u]=mal++;
}
double res[N];
void dfs(int u){
for(int i=head[u];i;i=e[i].nx){
int v=e[i].to;
res[v]=res[u]+(siz[u]-siz[v]+1)/2.0;
dfs(v);
}
}
int main(){
int n;
init();
scanf("%d",&n);
for(int i=2;i<=n;i++){
scanf("%d",&pre[i]);
deg[pre[i]]++;
addedge(pre[i],i);
}
res[1]=1;
queue<int> Q;
for(int i=1;i<=n;i++){
if(deg[i]==0)Q.push(i);
}
while(Q.size()){
int u=Q.front();Q.pop();
siz[u]++;
siz[pre[u]]+=siz[u];
if(--deg[pre[u]]==0)Q.push(pre[u]);
}
dfs(1);
for(int i=1;i<=n;i++){
printf("%8lf ",res[i]);
}
}
CodeForces - 699E - G - LRU
因为操作非常多次,所以最终的概率分布可以近似看作是稳态下的概率.那么:
对于任意一个
n
n
n长度的排列
P
P
P,若
P
(
k
)
P_{(k)}
P(k)表示第一个元素与第
k
k
k个元素交换.
d
p
[
P
]
=
∑
k
=
1
n
p
(
P
k
)
d
p
[
P
(
k
)
]
dp[P]=\sum_{k=1}^n p(P_k)dp[P_{(k)}]
dp[P]=k=1∑np(Pk)dp[P(k)]
所以:
d
p
[
P
]
=
∑
k
=
2
n
p
(
P
k
)
1
−
p
(
P
1
)
d
p
[
P
(
k
)
]
dp[P]=\sum_{k=2}^n \frac{p(P_k)}{1-p(P_1)}dp[P_{(k)}]
dp[P]=k=2∑n1−p(P1)p(Pk)dp[P(k)]
这就消去了自环的影响.
再考虑替换的计算:
P
=
[
a
1
a
2
…
a
k
]
→
P
′
=
[
a
i
a
1
…
a
k
−
1
]
⇔
P
′
′
=
[
a
1
…
a
k
−
1
]
→
P
′
=
[
a
i
P
′
′
]
P=[a_1\ a_2\dots\ a_k]\to P'=[a_i\ a_1\dots\ a_{k-1}]\Leftrightarrow P''=[ a_1\dots\ a_{k-1}]\to P'=[a_i\ P'']
P=[a1 a2… ak]→P′=[ai a1… ak−1]⇔P′′=[a1… ak−1]→P′=[ai P′′]
再对
P
′
′
P''
P′′中元素的全排列分类相加.可以知道这种递推是与位置无关的.设
I
I
I是布尔向量,那么:
d
p
[
I
]
=
∑
i
∈
I
∑
J
=
I
−
i
p
(
i
)
1
−
p
(
J
)
d
p
[
J
]
dp[I]=\sum_{i\in I}\sum_{J=I-i}\frac{p(i)}{1-p(J)}dp[J]
dp[I]=i∈I∑J=I−i∑1−p(J)p(i)dp[J]
#include <cstdio>
#include <algorithm>
using namespace std;
double p[25];
double dp[1<<21],res[21];
int main(){
int n,k,s=0;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%lf",&p[i]);
if(p[i]<1e-6)s++;
}
k=min(k,n-s);
dp[0]=1;
double base;int sel=0;
for(int i=0;i<(1<<n);i++){
base=0;sel=0;
for(int j=0;j<n;j++){
if((i>>j)&1){
sel++;
}else base+=p[j];
}
if(sel>=k)continue;
for(int j=0;j<n;j++){
if(((i>>j)&1)==0){
dp[i|(1<<j)]+=dp[i]*p[j]/base;
}
}
}
for(int i=0;i<(1<<n);i++){
sel=0;
for(int j=0;j<n;j++){
if((i>>j)&1)sel++;
}
if(sel!=k)continue;
for(int j=0;j<n;j++){
if(((i>>j))&1){
res[j]+=dp[i];
}
}
}
for(int i=0;i<n;i++){
printf("%.8lf ",res[i]);
}
}
CodeForces - 691E - H - Xor-sequences
这一题应该可以说是裸题了,求一个图上长度为
k
k
k的游动数量…
设
J
J
J是全一列向量,
M
M
M是图度矩阵.那么总的游动数量为:
σ
G
(
k
)
=
J
T
M
k
−
1
J
\sigma_G(k)=J^T M^{k-1}J
σG(k)=JTMk−1J
#include <cstdio>
#include <cstring>
long long a[200];
typedef long long Matrixtype;
const int Dim=101;
const Matrixtype mod=1e9+7;
struct Matrix{
Matrixtype a[Dim][Dim];
inline Matrixtype* const operator[](const int _i){return a[_i];}
void setsiz(int siz){a[0][0]=siz;}
void empty(int siz=0){
if(siz){a[0][0]=siz;for(int i=a[0][0];i;i--)for(int j=a[0][0];j;j--)a[i][j]=0;}
else memset(a,0,sizeof(a));
}
void I(int siz){a[0][0]=siz;for(int i=siz;i;i--)for(int j=siz;j;j--)a[i][j]=(i==j);}
void J(int siz){a[0][0]=siz;for(int i=siz;i;i--)for(int j=siz;j;j--)a[i][j]=1;}
void copy(Matrix &b){
a[0][0]=b[0][0];
for(int i=a[0][0];i;i--){
for(int j=a[0][0];j;j--)a[i][j]=b[i][j];
}
}
void prt(){
puts("--------------");
for(int i=1;i<=a[0][0];i++,puts("")){
for(int j=1;j<=a[0][0];j++)
//printf("%d ",a[i][j]);
printf("%I64d ",a[i][j]);
}
}
Matrix operator*(Matrix &b)const{
Matrix res;
res[0][0]=a[0][0];
for(int i=a[0][0];i;i--){
for(int j=a[0][0];j;j--){
res[i][j]=0;
for(int k=a[0][0];k;k--){
res[i][j]+=a[i][k]*b[k][j];
res[i][j]%=mod;
}
}
}
// for(int i=a[0][0];i;i--){
// for(int j=a[0][0];j;j--){
// res[i][j]%=mod;
// }
// }
return res;
}
void pow(Matrixtype n,Matrix &res){
Matrix x;
res.I(a[0][0]);
x.copy(*this);
while(n){
if(n&1)res=res*x;
x=x*x; n>>=1;
}
}
};
Matrix X[(sizeof(Matrixtype)<<3)+1],D,res;
void premat(Matrixtype n,Matrix &Mat){
int k=1;X[0].copy(Mat);
while(n>>k){
X[k]=X[k-1]*X[k-1];k++;
}
}
void prepow(Matrixtype n,Matrix &res){
res.I(X[0][0][0]);
for(int bit=0;n>>bit;bit++){
if((n>>bit)&1)res=res*X[bit];
}
}
bool judge(long long a,long long b){
a^=b;
b=0;
while(a){
if(a&1)b++;
a>>=1;
}
return (b%3)==0;
}
int main(){
int n;long long k;
scanf("%d%I64d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
}
D.I(n);
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(judge(a[i],a[j]))D[j][i]=D[i][j]=1;
}
}
premat(k,D);
prepow(k-1,res);
long long ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans+=res[i][j];
ans%=mod;
}
}
printf("%I64d\n",ans);
}