随笔- 19  文章- 0  评论- 0  阅读- 838 

Educational Codeforces Round 174 (Rated for Div. 2) C题解析

题目链接

题目描述🥰

题目思路😀

首先这个题目,我们可以通过观察美丽序列的定义,我们可以发现一个很明显的性质:数组的开头一定是最小值,数组的末尾一定是最大值

我们首先会想到一个思路,我们可以直接计算每一个以1开头,以3结尾的序列中间的2的个数,假设是n个,那么对答案的贡献就是Cn1+Cn2+Cn3+...+Cnn,也就是2n-1,但是在寻找到每一个1的时候,都需要遍历一遍数组结尾找3,这样的时间复杂度会很高,O(n^2)的时间复杂度显然无法解决这道题。

       int n;
	cin>>n;
	vector<int>a(n+1);
	for(int i=1;i<=n;i++)cin>>a[i];
	int ans=0;
	vector<int>sum(n+1);
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(a[i]==2);
	for(int i=1;i<=n;i++)
	{
		if(a[i]==1)
		{
		   for(int j=i+1;j<=n;j++)
		   {
			  if(a[j]==3){
			  	ans=(ans-1+qmi(2,sum[j]-sum[i-1],MOD))%MOD;
			  }
		   }
		 }
	}
	cout<<ans<<endl;

 但是事实上我们只需要每一次统计前面的1的出现次数和前面12串的出现次数,这样当遇到3的时候,就可以直接把3接到前面每一个12串的后面,也就成了一个个美丽序列。

步骤如下:

  1. 如果遇到的是1,那么我们就需要把已经出现的1的次数加1,为了后面的和2拼凑成半个美丽序列。
  2. 如果遇到的是2,那么我们可以把2接到前面的12串后面,还可以把2接到前面的所有1的后面,这两种方式都可以拼凑成半个美丽序列。
  3. 如果遇到的是3,那么我们直接把3接到前面所有的12串后面即可。

AC代码🧠

#include <bits/stdc++.h>

#define dev1(a) cout << #a << '=' << a << endl;
#define dev2(a, b) cout << #a << " = " << a << "  " << #b << " = " << b << endl;
#define dev3(a, b, c) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << endl;
#define dev4(a, b, c, d) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << endl;
#define dev5(a, b, c, d, e) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << "  " << #e << " = " << e << endl;
#define vec(a)                         \
    for (int i = 0; i < a.size(); i++) \
        cout << a[i] << ' ';           \
    cout << endl;
#define darr(a, _i, _n)               \
    cout << #a << ':';                \
    for (int ij = _i; ij <= _n; ij++) \
        cout << a[ij] << ' ';         \
    cout << endl;           
#define cin(a,n)           \
     for(int i=0;i<n;i++) \
      cin>>a[i];          
#define endl "\n"
#define pow pim
int pim(int a,int k)
{
    int res=1;
    if(a==0)return 0;
    while(k) 
    {
        if(k&1)res=(int)res*a;
        k>>=1;
        a=(int)a*a;
    }
    return res;
}
#define fi first
#define se second
#define caseT \
    int T;    \
    cin >> T; \
    while (T--)
#define int long long
// #define int __int128

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;
void solve()
{
	   int  ans = 0, a = 0,b = 0;
        int n;
        cin >> n;
        for (int l = 0; l < n; l++)
        {
            int k;
            cin >> k;
            if (k == 1)
            {
                a++;  //记录当前位置之前出现数字1的个数
            }else if (k == 2)
            {
            	//b变量是用来记录以数字2结尾且满足美丽子序列条件(前面有1)的子序列数量
                b = (b * 2 + a)% MOD; //当再出现一个2,可以接到前面的所有的以2结尾的序列后面和所有的以1结尾后面
            }else if (k==3)
            {
            	//在满足前置条件的所有的b个12串后面接一个3,计算答案
                ans = (ans + b)% MOD;
            }
        }
        cout << ans <<endl;
}
signed main()
{
    int t;
    cin >> t;
   while(t--)
    {
        solve();
    }
    return 0;
}

 

 posted on   熙玺  阅读(133)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

Shu-How Zの小窝

Loading...
点击右上角即可分享
微信分享提示