[Pause] Qingcheng A1295 necklace

Test question source

Tsinghua University 2011 Summer Camp for 100 Outstanding High School Students in Informatics

Problem Description

Someone is going to give you a gemstone necklace that contains N colorful (M colors in total) gems. Since you only care about the color of each gem in this question, and the necklace is not yet joined at the two ends, it can be thought of as a string of numbers.
You want to see a continuous stretch of gems of the same color among the colorful gems. Therefore, you define the luck of a gemstone necklace as the length of its longest continuous substring of gemstones of the same color. For example, necklace 112322211 has a luck of 3 because it includes substring 222 made of gemstones of the same color. The two 11s at the beginning and the end do not constitute a continuous 1111, because the necklace is now a string instead of a ring.
However, you haven't seen this necklace yet. You only know the probability that each gem is each color. Also, the color distribution of each gemstone is known to be independent. Now you want to calculate before actually seeing this necklace, what is the expected luck of this necklace?

input format

The first line of input has two positive integers N and M.
Each of the following N lines has M non-negative real numbers. The number P_(i,j) in the i-th row and the j-th column means that the probability that the i-th gemstone is the color j is P_(i,j). The M real numbers in each row are guaranteed to sum to 1.

output format

A real number, the expected luck of this necklace. Round to 6 decimal places.

sample input

4 2
1.0 0.0
0.5 0.5
0.0 1.0
0.5 0.5

Sample output

2.250000

Sample description

We use 1 and 2 to represent the two colors of gemstones, so this necklace has four equal probabilities: 1121, 1122, 1221 and 1222. Their luck is 2, 2, 2, 3, so the expected luck is 2.25.

Data size and conventions

30% of the data satisfy N≤16, M≤3.
60% of the data satisfy N≤100.
100% of the data satisfy 2≤N≤1000, 2≤M≤10.

answer

First of all, think of the dp of 60 points, let \(f[i][j][k][t]\) represent the \(i\)th bit, the longest continuous segment length is \(j\) , the end The length of the continuous segment is \(k\) , the probability of the last digit being \(t\) , and then violently transferred
This is the 60-point program:

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100+10,MAXM=10+10;
int n,m;
db ans,f[MAXN][MAXN][MAXN][MAXM],P[MAXN][MAXM];
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
    read(n);read(m);
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=m;++j)scanf("%lf",&P[i][j]);
    for(register int i=1;i<=m;++i)f[0][0][0][i]=1.0;
    for(register int i=0;i<n;++i)
        for(register int j=0;j<=i;++j)
            for(register int k=0;k<=j;++k)
                for(register int t=1;t<=m;++t)
                {
                    if(k<j)f[i+1][j][k+1][t]+=f[i][j][k][t]*P[i+1][t];
                    else f[i+1][j+1][k+1][t]+=f[i][j][k][t]*P[i+1][t];
                    for(register int p=1;p<=m;++p)
                        if(t==p)continue;
                        else f[i+1][j][1][p]+=f[i][j][k][t]*P[i+1][p];
                }
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=i;++j)
            for(register int k=1;k<=m;++k)ans+=f[n][i][j][k]*i;
    printf("%.6f\n",ans);
    return 0;
}

Then, press one dimension, ignoring the length of a certain continuous segment, and subtract the probability that the length of the new continuous segment exceeds \(j\) when transferring to ensure that the continuous segment in the considered position must not be greater than \(j \)
Set \(f[i][j][k]\) to represent the \(i\)th bit, the length of the continuous segment does not exceed \(j\) , the probability that the color at the end is \(k\) , \ (g[i][j][k]\) represents the probability from the \(i\)th bit to the \(j\)th bit, during which the colors are all \(k\) , \(s[i][ j]\) is to the \(i\)th bit, the probability that the length of the continuous segment does not exceed \(j\)
Then
\(s[i][j]=\sum_{k=1}^mf[i][ j][k]\) , this is easy to understand
\(f[i][j][k]=s[i-1][j]*g[i][i][k]-(s[ij -1][j]-f[ij-1][j][k])*g[ij][i][k]\)
This thing is a bit complicated
. First of all, if you do not ensure that the length of the continuous segment must not be greater than \( j\) , the probability is\(s[i-1][j]*g[i][i][j]\) , this thing must be subtracted from the illegal situation, the only illegal situation is to add this new number, The length of the continuous segment at the end becomes \(j+1\) , that is , all \(k\) colors during the period from \(ij\) to \(i\) . So that's what's subtracted from the back. \(s[ij-1][j]\) minus \(f[ij-1][j][k]\) is to ensure that \(ij-1\) cannot be \(k\ ) color, because if it is a \(k\) color, then the length of the continuous segment at the end is more than \(j+1\) , in this case, the AC program has been reduced before the transfer :

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=1000+10,MAXM=10+10;
int n,m;
db ans,f[MAXN][MAXN][MAXM],P[MAXN][MAXM],g[MAXN][MAXN][MAXM],s[MAXN][MAXN];
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
    read(n);read(m);
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=m;++j)scanf("%lf",&P[i][j]);
    for(register int k=1;k<=m;++k)
        for(register int i=1;i<=n;++i)
        {
            g[i][i][k]=P[i][k];
            for(register int j=i+1;j<=n;++j)g[i][j][k]=g[i][j-1][k]*P[j][k];
        }
    for(register int i=1;i<=n;++i)s[0][i]=1;
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=n;++j)
            for(register int k=1;k<=m;++k)
            {
                f[i][j][k]=s[i-1][j]*g[i][i][k];
                if(i-j-1>=0)f[i][j][k]-=(s[i-j-1][j]-f[i-j-1][j][k])*g[i-j][i][k];
                s[i][j]+=f[i][j][k];
            }
    for(register int i=1;i<=n;++i)ans+=(s[n][i]-s[n][i-1])*i;
    printf("%.6f\n",ans);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325115852&siteId=291194637