题目
Description
Input
Output
Sample Input
5 3
0 100000000 200000000 700000000 0 0 0 0 0 0
0 600000000 150000000 250000000 0 0 0 0 0 0
0 333333333 333333334 333333333 0 0 0 0 0 0
0 0 0 450000000 550000000 0 0 0 0 0
0 999999998 1 1 0 0 0 0 0 0
123
Sample Output
0.004999999995000
0.090000000180000
0.000000000000000
Data Constraint
思路
考虑每个数字的贡献
每个位置找到一个最大的值,将这个最大值的字符找出来变成一
个字符串。预处理如果匹配出一段区间的位置的概率。
如果串m这里跟最大的概率的字符不同,那么这个概率一定小
于0.5,这样的点不会超过log个。
每次找到两个串的后缀的lcp,将匹配的概率乘起来,这样的操
作在log次之后就会小于1e-9。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7,N=1e6+77;
const double eps=1e-9;
ll pre1[N],pre2[N],_10[N],a[N][11],b[N],c[N],n,m,yjy;
char st[N];
double aii[N],p;
char ch;
bool check(ll x,ll y,ll mid)
{
ll u=(pre1[x+mid]-pre1[x-1]*_10[mid+1]%mod+mod)%mod,v=(pre2[y+mid]-pre2[y-1]*_10[mid+1]%mod+mod)%mod;
if(u==v) return 1;
return 0;
}
ll power(ll x,ll t)
{
ll b=1;
while(t)
{
if(t&1) b=b*x%mod;
x=x*x%mod; t>>=1;
}
return b;
}
void init()
{
for(int i=1; i<=n; i++)
{
yjy=0;
for(int j=0; j<=9; j++)
{
scanf("%lld",&a[i][j]);
if(a[i][j]>a[i][yjy]) yjy=j;
}
b[i]=yjy;
}
scanf("%s",st+1);
for(int i=1; i<=n; i++) c[i]=st[i]-'0';
_10[1]=10;
for(int i=2; i<=n; i++) _10[i]=_10[i-1]*10%mod;
for(int i=1; i<=n; i++) pre1[i]=(pre1[i-1]*10%mod+b[i])%mod;
for(int i=1; i<=m; i++) pre2[i]=(pre2[i-1]*10%mod+c[i])%mod;
for(int i=1; i<=m; i++) p=p*a[i][b[i]]/1000000000;
}
int main()
{
freopen("password.in","r",stdin);freopen("password.out","w",stdout);
scanf("%lld%lld",&n,&m);
p=1;
init();
for(int i=1; i<=n-m+1; i++)
{
int x=i,y=1;
aii[i]=p;
ll cnt=0;
while(aii[i]>eps&&y<=m)
{
int l=-1,r=m-y-1;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(x,y,mid)==1) l=mid;else r=mid-1;
}
int s=l;
aii[i]=aii[i]*a[x+s+1][c[y+s+1]]/a[x+s+1][b[x+s+1]];
x=x+s+2,y=y+s+2;
cnt++;
}
p=p/a[i][b[i]]*a[i+m][b[i+m]];
}
for(int i=1; i<=n-m+1; i++) printf("%.10lf\n",aii[i]);
}