Description:
刚开始你有一个数字 0 ,每一秒钟你会随机选择一个
Solution:
如果令 Fi(x) 表示在进行完 i 次操作之后,手上的数为
Ans=∑i=1∞(Fi(U)−Fi−1(U))∗i=F∞(U)−∑i=0∞Fi(U)
其中
Fi(x)=∑ax∑bx[a|b=x]Fi−1(a)∗P(b)
令 Gi(x)=∑xj|x=xFi(j),那么
Gi(x)=∑a|x=x∑b|x=xFi−1(a)∗P(b)=∑a|x=xFi−1(a)∗∑b|x=xP(b)=(∑b|x=xP(b))i=G1(x)i
观察 Gi(x) 的定义式 Gi(x)=∑xj|x=xFi(j) ,令函数 C(x) 表示 x 的二进制表示中有多少个
Fi(x)=∑s|x=x(−1)C(x)−C(s)Gi(s)=∑s|x=x(−1)C(x)−C(s)G1(s)i
所以:
Ans=F∞(U)−∑i=0∞∑s|U=U(−1)C(U)−C(s)G1(s)i=F∞(U)−∑s|U=U(−1)C(U)−C(s)∑i=0∞G1(s)i
求和可得:
Ans=∑s|x=x(−1)C(U)−C(s)G1(U)∞+∑s|U=U and s≠U(−1)C(U)−C(s)1G1(s)−1−∑i=0∞G1(U)i
Ans=∞+∑s|U=U and s≠U(−1)C(U)−C(s)1G1(s)−1−∞=∑s|U=U and s≠U(−1)C(U)−C(s)1G1(s)−1
怎么判断无解,只用看看最后算出来的Ans是不是收敛的,如果是的,就是有解,否则输出 INF
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int N;
double P[2000010]={0};
int N2;
double S[2000010]={0};
int Num[2000010]={0};
int main()
{
cin>>N;
N2=1<<N;
for(int i=0;i<N2;i++)
{
scanf("%lf",&P[i]);
S[i]=P[i];
}
for(int i=0;i<N;i++)
{
for(int j=0;j<N2;j++)
if(j&(1<<i))
{
S[j]+=S[j^(1<<i)];
Num[j]++;
}
}
for(int i=0;i<N2-1;i++)
if(S[i]>=1-1e-8)
{
cout<<"INF"<<endl;
return 0;
}
double Ans=0;
for(int i=0;i<N2-1;i++)
{
if((N-Num[i])&1)
Ans-=1/(S[i]-1);
else Ans+=1/(S[i]-1);
}
printf("%.10lf\n",Ans);
return 0;
}