这题带着期望的幌子,实际上是个数学题.
题意
给 两 个 长 度 相 等 都 为 n 的 字 符 串 a , b . 定 义 两 个 长 度 相 等 都 为 n 的 字 符 串 s , t 的 某 个 函 数 f ( s , t ) = ∑ i = 1 n [ s i = t i ] . 求 随 机 分 别 选 择 a , b 的 一 个 子 串 s , t 时 f ( s , t ) 的 期 望 . 给两个长度相等都为n的字符串a,b.\newline 定义两个长度相等都为n的字符串s,t的某个函数f(s,t)=\sum_{i=1}^{n}[s_i=t_i]. \newline求随机分别选择a,b的一个子串s,t时f(s,t)的期望. 给两个长度相等都为n的字符串a,b.定义两个长度相等都为n的字符串s,t的某个函数f(s,t)=∑i=1n[si=ti].求随机分别选择a,b的一个子串s,t时f(s,t)的期望.
解法
求出两个字符串所有子串的 f f f函数值和除以 1 2 + 2 2 + 3 2 + . . . + n 2 1^2+2^2+3^2+...+n^2 12+22+32+...+n2.
在字符串 s s s中,如果有某一个字符 a a a,位置是 i i i, t t t中也有同样的字符 a a a,位置是 j j j,我们来思考一下这对相同字符的贡献.
从 1 → i 1\to i 1→i,这些都是起点,从 j → n j\to n j→n,这些都是终点.
如果 i < j i<j i<j,答案就是 i × ( n − j + 1 ) i\times(n-j+1) i×(n−j+1),否则答案是 j × ( n − i + 1 ) . j\times(n-i+1). j×(n−i+1).
普通处理是 O ( n 2 ) O(n^2) O(n2)的,如何处理到 O ( n ) O(n) O(n)呢?
我们在扫位置的时候开两个 c n t cnt cnt数组,表示当前两个字符串中某个字母出现了几次.
我们用 c n t [ a [ i ] ] + = i cnt[a[i]]+=i cnt[a[i]]+=i来处理前缀数字.
加的结果连 l o n g l o n g long \ long long long都会爆,要用 d o u b l e double double来存.
这样就没有问题了.
谢谢大家.
#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rel register ll
#define rec register char
#define gc getchar
//#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?-1:*p1++)
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
char buf[1<<23],*p1=buf,*p2=buf;
inline int read(){
int x=0,f=1;char c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return f?x:-x;
}
template <typename mitsuha>
inline bool read(mitsuha &x){
x=0;int f=1;char c=gc();
for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
if (!~c) return 0;
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return x=f?x:-x,1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return 0&pc(48);
if (x<0) pc('-'),x=-x;
int bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
return 0;
}
inline char fuhao(){
char c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
const int yuzu=2e5;
typedef double db;
typedef ll fuko[yuzu|10];
typedef char norie[yuzu|10];
norie c,d; fuko a,b;
int main() {
int n=read(),i;
scanf("%s%s",c+1,d+1);
db llx=0;
for (i=1;i<=n;++i)
a[d[i]]+=i,llx+=1.0*(n-i+1)*(a[c[i]]+b[d[i]]),b[c[i]]+=i;
printf("%.12lf\n",llx*6/n/(n+1)/(n*2+1)); // 平方和公式.
}