Codeforces 204C Little Elephant and Furik and Rubik 纯数学

文章目录


这题带着期望的幌子,实际上是个数学题.

题意

给 两 个 长 度 相 等 都 为 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)的期望. na,b.ns,tf(s,t)=i=1n[si=ti].a,bs,tf(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 1i,这些都是起点,从 j → n j\to n jn,这些都是终点.
如果 i &lt; j i&lt;j i<j,答案就是 i × ( n − j + 1 ) i\times(n-j+1) i×(nj+1),否则答案是 j × ( n − i + 1 ) . j\times(n-i+1). j×(ni+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)); // 平方和公式.
}

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/83535790