LG10384

一道相当不错的概率题。

首先考虑种子中存在 \(\verb!aa!\) 的情况。显然,我们可以让每个不是 \(\verb!aa!\) 的种子都与这个 \(\verb!aa!\) 型的种子杂交,并检验杂交后的性状。若为 \(\verb!a!\),则一定为 \(\verb!Aa!\),否则可能是 \(\verb!AA!\)\(\verb!Aa!\)。不难想到多杂交几次,如果一直都显现出 \(\verb!A!\) 则可以认为就是 \(\verb!AA!\)。取杂交次数为 \(15\) 次时,错误率在 \(2^{-15}\) 左右,完全可以接受。

如果种子中不存在 \(\verb!aa!\),这样做不能够保证正确性。换一种思路想,对于给定的任意两颗种子,其可能的情况有 \(\{ \verb!AA!,\verb!AA! \},\{ \verb!AA!,\verb!Aa! \},\{ \verb!Aa!,\verb!AA! \},\{ \verb!Aa!,\verb!Aa! \}\) 四种。第四种情况最好检验,有 \(\frac{1}{4}\) 的概率出现 \(\verb!a!\),而别的情况则不可能出现,因此做多几次杂交即可判断这种情况。

对于剩下的三种情况,继续分类讨论。显然,如果是 \(\{ \verb!AA!\ ,\verb!AA! \}\),无论如何杂交都是 \(\verb!AA!\)。但如果是 \(\{ \verb!AA!\ ,\verb!Aa! \}\)\(\{ \verb!Aa!\ ,\verb!AA! \}\),其子代中很大概率有 \(\verb!Aa!\) 的出现。又由于两个亲代中一定有一个 \(\verb!Aa!\),因此可能杂交出 \(\verb!aa!\)。如果出现了 \(\verb!aa!\),则可以证明上述的情况。如果所有子代与亲代杂交都没有 \(\verb!aa!\),则可以认为亲本都是 \(\verb!AA!\)。又因为 \(15 \times 3 \times 10^4 = 4.5\times 10^5\),因此杂交 \(15\) 次是较为合适的。此时的错误率也较低,交多几次就可以通过了。

如果杂交次数过多而无法通过,可以考虑一个简单的优化:如果当前已经杂交出了 \(\verb!aa!\),则对剩余的种子可以直接用文章最前面的方法判断即可。

AC 记录

#include <bits/stdc++.h>

using namespace std;

char query(int k);
void cross(int i, int j);

int a[1000001];

vector<string> guess(int n)
{
	srand( time( 0 ) );
	vector<string> ans;
	int cnt = n,tot = 0,d = 0,flag,lst;
	char c;
	for( int i = 1 ; i <= n ; i ++ )
	{
		c = query( i );
		if( c == 'a' )
		{
			a[i] = 3;
			if( !d ) d = i;
		}
	}
	if( d )
	{
		for( int i = 1 ; i <= n ; i ++ )
		{
			if( a[i] == 3 ) continue;
			flag = 0;
			for( int t = 1 ; t <= 15 ; t ++ )
			{
				cnt ++;
				cross( i , d );
				if( query( cnt ) == 'a' )
				{
					flag = 1;
					break;
				}
			}
			if( flag ) a[i] = 2;
			else a[i] = 1;
		}
		for( int i = 1 ; i <= n ; i ++ )
		{
			if( a[i] == 1 ) ans.push_back( "AA" );
			if( a[i] == 2 ) ans.push_back( "Aa" );
			if( a[i] == 3 ) ans.push_back( "aa" );
		}
		return ans;
	}
	int i;
	for( i = 1 ; i <= n && !d ; i += 2 )
	{
		lst = cnt;
		for( int t = 1 ; t <= 14 && !d ; t ++ )
		{
			cnt ++;
			cross( i , i + 1 );
			if( query( cnt ) == 'a' )
			{
				d = cnt;
				a[i] = 2,a[i + 1] = 2;
				break;
			}
		}
		for( int t = 1 ; t <= 14 && !d ; t ++ )
		{
			cnt ++;
			cross( lst + t , i );
			if( query( cnt ) == 'a' )
			{
				d = cnt;
				a[i] = 2;
				break;
			}
			cnt ++;
			cross( lst + t , i + 1 );
			if( query( cnt ) == 'a' )
			{
			    a[i + 1] = 2;
				d = cnt;
				break;
			}
		}
		if( !a[i] ) a[i] = 1;
		if( !a[i + 1] ) a[i + 1] = 1;
	}
	for(  ; i <= n ; i ++ )
	{
		flag = 0;
		for( int t = 1 ; t <= 14 ; t ++ )
		{
			cnt ++;
			cross( i , d );
			if( query( cnt ) == 'a' )
			{
				flag = 1;
				break;
			}
		}
		if( flag ) a[i] = 2;
		else a[i] = 1;
	}
	for( int i = 1 ; i <= n ; i ++ )
	{
		if( a[i] == 1 ) ans.push_back( "AA" );
		if( a[i] == 2 ) ans.push_back( "Aa" );
		if( a[i] == 3 ) ans.push_back( "aa" );
	}
	return ans;
}
posted @ 2024-05-18 17:29  liyilang2021  阅读(1)  评论(0编辑  收藏  举报