Journey to Un‘Goro 贪心,找规律,搜索(沈阳)

在这里插入图片描述
题意 :

  • 让我们构造一个长度为n的只包含’b’和‘r’的字符串,要求所构造的字符串的子序列满意的个数最多
  • 满意的定义:对于序列[l,r],其中’r’出现的个数是奇数,那么就是满意的
  • 按字典序输出前100个

思路 :

  • 找最大对数,肯定是全r最优,直接计算即可
  • 首先需要求 [ l , r ] [l,r] [l,r]内‘r’的个数,可以想到前缀和
  • 我们定义数组 g [ N ] g[N] g[N] g [ i ] g[i] g[i]表示字符串前i位里r出现的个数
  • 那么对于序列 [ l , r ] [l,r] [l,r],r出现的个数就是 g [ r ] − g [ l − 1 ] g[r] - g[l - 1] g[r]g[l1]
  • 只有 g [ r ] g[r] g[r] g [ l − 1 ] g[l - 1] g[l1]的奇偶性不一致时,r出现的个数会是奇数,该字符串才满意
  • 设这些前缀和中有x个奇数,y个偶数,则满足 x + y = n x+y=n x+y=n,且此时我们的答案就是 x ∗ y x*y xy
  • 则由均值不等式 x + y ≥ 2 x y x + y \geq 2\sqrt{xy} x+y2xy 得到 x y ≤ ( x + y 2 ) 2 xy \leq (\frac{x+y}{2})^2 xy(2x+y)2,当且仅当x=y时取等号
  • x = y = n 2 x=y=\frac{n}{2} x=y=2n时,答案最大
  • 因为只需要输出前100个,搜索即可
  • x*y为 n + 1 2 ∗ n + 2 2 \frac{n+1}{2} * \frac{n+2}{2} 2n+12n+2,x和y分别不能超过 n + 2 2 \frac {n+2}{2} 2n+2
  • dfs传入四个参数,当前字符串的第i位,当前字符串的前缀和为奇数的个数,为偶数的个数,前i-1位r的个数
  • dfs时首先判断已经输出字符串的个数和前缀和分别为奇数偶数的个数
  • 然后是判断当前这位是否已经第n位
  • 再根据前i-1位r的个数分别dfs
  • 观察样例1,n=1时,输出"r",第0位以前的‘r’的个数的前缀和是0,偶数,因此dfs第一次传入参数在第二个位置应为1
  • 字典序最小表现在每次dfs都是先放b后放r的
  • 注意要开long long,因为输出个数时溢出了
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
using namespace std;
typedef long long ll;

const int N = 1e5 + 10;

ll n;
ll out;
ll cnt = 0;
char s[N];

// 字符串中第i位,前缀和偶数个数,前缀和奇数个数,字符串前i-1位r的个数
void dfs(ll i, ll even, ll odd, ll last)
{
    
    
    // 输出100个,或者奇数或偶数数量超限
    if (cnt >= 100 || even > out || odd > out)
        return ;
    
    // 一个字符串完成
    if (i == n)
    {
    
    
        cnt ++ ;
        cout << s << endl;
        return ;
    }
    
    if (last % 2 == 0)  // 字符串前i-1位r的个数是偶数
    {
    
    
        s[i] = 'b';
        dfs(i + 1, even + 1, odd, last);    // 在第i位放'b',前缀和为偶数的个数加一,为奇数的个数不变
        s[i] = 'r';
        dfs(i + 1, even, odd + 1, last + 1);
    }
    else                // 字符串前i-1位r的个数是奇数
    {
    
    
        s[i] = 'b';
        dfs(i + 1, even, odd + 1, last);
        s[i] = 'r';
        dfs(i + 1, even + 1, odd, last + 1);
    }
}

int main()
{
    
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    
    cin >> n;
    
    cout << ((n + 1) / 2) * ((n + 2) / 2) << endl;

	//	LL ans = 1;
	//	LL tmp = 1;
	//	for(int i = 2; i <= n; i ++ )
	//	{
    
    
	//		if(i % 2) tmp ++;
	//		ans += tmp;
	//	}
	//	m = (n + 2) / 2;
	//	cout << ans << endl;
    
    out = (n + 2) / 2;
    
    dfs(0, 1, 0, 0);
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_51448653/article/details/121275122
un