题解 exp

传送门

因为是在补题解所以所有公式都省了

解释一下当时不太能理解的地方

\[f_{l, r}=\frac{1}{g_{l, r}}\sum\limits_{k=l}^{r-1}p_{l, r, k}(f_{l, k}+f_{k+1, r}+\frac{k-l}{2}) \]

这里这个 \(\frac{1}{g_{l, r}}\)
由于 \(g_{l, r}=\sum p_{l, r, k}\)
所以这里相当于在算加权平均数,其中 \(f_{l, k}+f_{k+1, r}+\frac{k-l}{2}\) 是这个权

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 405
#define ll long long
//#define double long double
//#define int long long

int n;
char s[N];

namespace force{
	unordered_map<int, double> mp;
	double pre;
	double dfs(int s) {
		// cout<<"s: "<<bitset<5>(s)<<endl;
		double ans=0;
		if (!s) return 0.0;
		if (mp.find(s)!=mp.end()) return mp[s];
		for (int k=1; k<=n; ++k) {
			// cout<<"k: "<<k<<endl;
			double add=0;
			int now=k;
			while (!(s&(1<<now))) {
				++add;
				now=(now%n)+1;
			}
			add+=dfs(s^(1<<now));
			// cout<<"add: "<<add<<endl;
			ans+=pre*add;
		}
		return mp[s]=ans;
	}
	void solve() {
		mp.clear();
		int tem=0;
		for (int i=1; i<=n; ++i) if (s[i]=='.') tem|=1<<i;
		pre=1.0/n;
		printf("%.9lf\n", dfs(tem));
	}
}

namespace task{
	int sum[N];
	double fac[N], inv[N], F[N][N], G[N][N], P[N][N], ans;
	inline double qpow(double a, int b) {double ans=1; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
	inline double C(int n, int k) {return fac[n]*inv[k]*inv[n-k];}
	double g(int l, int r);
	double p(int l, int r, int k) {
		if (s[r]=='X'||s[k]=='X') return 0;
		// if (P[l][r][k]>0) return P[l][r][k];
		int lc=sum[k-1]-sum[l-1], rc=sum[r-1]-sum[k];
		// return P[l][r][k]=C(lc+rc, lc)*qpow((k-l+1.0)/(r-l+1.0), lc)*g(l, k)*qpow((r-k)/(r-l+1.0), rc)*g(k+1, r)*(k-l+1.0)/(r-l+1.0);
		return C(lc+rc, lc)*qpow((k-l+1.0)/(r-l+1.0), lc)*g(l, k)*qpow((r-k)/(r-l+1.0), rc)*g(k+1, r)*(k-l+1.0)/(r-l+1.0);
	}
	double g(int l, int r) {
		if (s[r]=='X') return 0;
		if (l==r) return 1;
		if (sum[r]-sum[l-1]==1) return 1;
		if (G[l][r]>0) return G[l][r];
		double ans=0;
		for (int k=l; k<r; ++k) ans+=p(l, r, k);
		return G[l][r]=ans;
	}
	double f(int l, int r) {
		// cout<<"f: "<<l<<' '<<r<<endl;
		if (l==r || s[r]=='X' || sum[r]-sum[l-1]==1) return 0;
		if (F[l][r]>0) return F[l][r];
		double ans=0;
		for (int k=l; k<r; ++k) ans+=p(l, r, k)*(f(l, k)+f(k+1, r)+(k-l)/2.0);
		// cout<<"return: "<<ans/g(l, r)<<endl;
		return F[l][r]=g(l, r)>0?ans/g(l, r):0;
	}
	void solve() {
		memset(F, 0xc2, sizeof(F));
		memset(G, 0xc2, sizeof(G));
		memset(P, 0xc2, sizeof(P));
		// cout<<double(sizeof(P))/1000/1000<<endl;
		fac[0]=fac[1]=1; inv[0]=inv[1]=1; ans=(n-1)/2.0;
		for (int i=2; i<=n; ++i) fac[i]=fac[i-1]*i;
		for (int i=2; i<=n; ++i) inv[i]=1.0/i;
		for (int i=2; i<=n; ++i) inv[i]=inv[i-1]*inv[i];
		for (int i=1; i<=n; ++i) s[n+i]=s[i];
		for (int i=1; ; ++i)
			if (i>n) {puts("0.000000000"); return ;}
			else if (s[i]=='.') break;
		for (int i=1; i<=2*n; ++i) sum[i]=sum[i-1]+(s[i]=='.');
		// cout<<"sum: "; for (int i=1; i<=n*2; ++i) cout<<sum[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) ans+=f(i, i+n-1)*g(i, i+n-1);
		printf("%.9lf\n", ans);
	}
}

signed main()
{
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%s", s+1);
		n=strlen(s+1);
		// force::solve();
		task::solve();
	}
	
	return 0;
}
posted @ 2022-01-11 21:39  Administrator-09  阅读(1)  评论(0编辑  收藏  举报