首页 > 其他分享 >P11269 【MX-S5-T3】IMAWANOKIWA (Construction ver.)

P11269 【MX-S5-T3】IMAWANOKIWA (Construction ver.)

时间:2025-01-20 19:31:43浏览次数:1  
标签:右边 ver int 可以 IMAWANOKIWA S5 消掉 答案 操作

P11269 【MX-S5-T3】IMAWANOKIWA (Construction ver.)

题目翻译:

对一个初始长度为 \(n\) 的序列 \(a\) 进行操作,每次操作可以任选两个相邻的数 \(a_j,a_{j+1}\) 将这两个数删去,在加上 \(popc(a_j+a_{j+1})\)

  • \(popc(x)\),表示 \(x\) 在二进制下 \(1\) 的个数
    而我们要求出一个操作序列,由于是删二加一,因此总共会有 \(n-1\)次操作,且最后会剩下一个数,而要求的就是使最后的数为 \(t\) 的最小字典序的操作序列。
  • 令操作序列 \(p_i\) 表示第 \(i\) 次操作所选择的 \(j\),则要求出字典序最小的操作序列。并将它进行转换变为答案。

性质分析:

因为只有 \(0,1,2\) 三个数,而每次操作只会选择两个数,我们可以先对每次的结果经行一个打表:

\(0\) \(1\) \(2\)
\(0\) \(0\) \(1\) \(1\)
\(1\) \(1\) \(1\) \(2\)
\(2\) \(1\) \(2\) \(1\)

根据该表可以很容易得到一下性质:

\(1.\)若只有 \(0\) 那最终答案一定只为 \(0\)

\(2.\)若只有 \(1\) 那最终答案一定只为 \(1\)

\(3.\)若只有 \(1,2\) 那最终答案一定只为 \(1\)

\(2.\)若只有 \(1,2\) 那最终答案跟 \(2\) 的奇偶有关,因为只有两个 \(2\) 才能消掉 \(2\)

\(t\) 情况讨论:

根据以上的性质发现,若既有 \(0\) 和 \(2\) 那答案就不唯一,那我们可以找不同的情况下的答案:

分析 \(0\) 的个数:

\(1.\)若 \(0\) 的个数为零,那只有形如 \(…12021…\)的形式结果才有可能为 \(2\),也就是中间一个 \(0\) 两边紧靠两个 \(2\),接着左右只有 \(1\)。其他情况答案都肯定为 \(1\) 理由如下:

因为一个 \(0\) 可以消掉一个 \(2\) 使其变为 \(1\),而会剩下一个 \(2\) 而 \(2\) 无法消掉 \(1\) 那最终答案很明显就是 \(2\)

其他情况也就是 \(2\) 在一侧或者大于数量大于 \(2\) 那\(2\)的奇偶性一定可以被 \(0\) 控制,若为偶可以消掉一个变为奇,若为奇那也可以消掉一个变为偶。若同时 \(2\) 自己也可以自行抵消,变为 \(1\) 在控制 \(0\),以此来控制 \(2\) 的奇偶性,所以答案只会为 \(1\)

若 \(0\) 的个数大于 \(1\),那最终答案一定可以为 \(1\),理由如下:

由于 \(2\) 可以消掉 \(1\), 而 \(1\) 又可以消掉 \(0\)然后又被 \(2\) 消掉,且 \(0\) 之间相互抵消,而 \(2\) 与 \(2\) 之间会抵消为 \(1\)。若先不考虑 \(0\) 与 \(2\) 之间的转换,那序列最终一定会变成 \(2,0\) 交替出现即\(2020202\)的形式,那中间的数相互抵消,最后也就为\(1\)。

那只需要判断 \(0,1,2\) 的个数和出现的位置,就能判断最终答案的 \(t\) 也就可以拿到 \(25\) 分的答案分

操作序列讨论:

要求出字典序最小,那尽量就从前面取。继续分论:

\(1.\)只有 \(0\) ,只有 \(1\),只有 \(0,1\),只有 \(1,2\) :

只需要一直消第一个即可

\(2.\)只有一个 \(0\):

  • 形如 \(12021\),已经知道情况:

也就一直消第一个即可

  • 若右边又偶数个 \(2\):

那么右边至少是可以自己消掉的,我们可以先操作第一个直到遇到 \(0\) 然后再分讨一下下一次操作是否会改变 \(2\) 的奇偶性。

  • 若左边又偶数个 \(2\):

那么此时右边是奇数个 \(2\),我们可以先操作第一个直到遇到 \(0\),然后再使 \(0\) 消掉右边的 \(2\)。

  • 若左右都只有奇数个 \(2\):

因为已经判掉了答案为 \(2\) 的情况,所以左右一定至少有一边可以用 \(1\) 消掉 \(0\)。为了保证字典序,我们应该优先用右边的 \(1\) 来消掉,这样左边就可以一直选第一个,若右边不合法才优先用左边的。

\(3.\)若 \(0\) 的个数大于 \(1\) :

我们显然可以先一直选第一个直到只剩下两个 \(0\),因为数量大于 \(1\) ,所以一定合法。

  • 若不看左边的 \(0\),右边可以将答案消为一:

那么直接按一个 \(0\) 的方案做就行了。

  • 若不看左边的 \(0\),右边不合法:

那么我们需要先用左边的 \(0\) 消掉一个 \(2\),剩下的就简单了。

完整代码:

#include<bits/stdc++.h>
#define ull unsigned long long
#define popc __builtin_popcount
using namespace std;
const int N=1e5+5; 
const int B=13331;
int n,T,cnt;
int sum[N],s[N];
ull pw[N],ans[N];
string t;
void get(int x){
    s[x+1]=popc(s[x]+s[x+1]);
}
void sol1(){
    int i,x;
    for(i=1,s[n+1]=1;i<=n;i++){
        if(s[i]==0){
            x=i;
            break;
        }
    }
    for(i=1;i<=n;i++){
        sum[i]=sum[i-1]+(s[i]==2);
    }
    if((sum[n]-sum[x])%2==0){
        for(i=1;i<x;i++){
            ans[++cnt]=1;
            get(i);
        }
        if(!s[x]){
            for(i=x+1;i<=n && s[i]==2;i++){
                ans[++cnt]=2;
                get(i);
            }
        }
    }
    else if(sum[x]%2==0){
        for(i=1;i<x-1;i++){
            ans[++cnt]=1;
        }
        for(i=x+1;i<=n && s[i]!=2;i++){
            ans[++cnt]=3-(x==1);
            get(i);
        }
        if(x>1){
            ans[++cnt]=2;
        }
    }
    else{
        if(sum[n]-sum[x]==1 && s[x+1]==2){
            if(s[x-1]==2){
                for(i=1;sum[x]-sum[i+1]>=2;i++){
                    ans[++cnt]=1;
                    get(i);
                }
                for(++i;i<x;i++){
                    ans[++cnt]=2;
                }
            }
            else{
                for(i=1;i<x-2;i++){
                    ans[++cnt]=1;
                }
                ans[++cnt]=2;
            }
        }
        else{
            for(i=1;i<x-1;i++){
                ans[++cnt]=1;
            }
            for(i=x+1;i<=n && s[i]==2;i++){
                ans[++cnt]=3;
                get(i);
            }
            ans[++cnt]=2;
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    freopen("popc.in","r",stdin);
    freopen("popc.out","w",stdout);
    int i,k,r,x,y;
    cin>>T;
    pw[0]=s[0]=1;
    for(i=1;i<N;i++)pw[i]=pw[i-1]*B;
    while(T--){
        cin>>t;
        n=t.size();
        ans[0]=cnt=0;
        r=n;
        for(i=1,s[n+1]=0;i<=n;i++){
            s[i]=t[i-1]-'0';
        }
        for(i=1,x=0;i<=n;i++){
            s[i]?0:(x++,y=i),sum[i]=sum[i-1]+(s[i]==2);
        }
        if(x==n){
            cout<<"0 ";
        }
        else if(!x){
            cout<<(sum[n]&1)+1<<" ";
        }
        else if(x==1 && sum[n]==2 && s[y+1]==2 && s[y-1]==2){
            cout<<"2 ";
        }
        else{
            cout<<"1 ";
        }
        if(x==n || !x || (x==1 && sum[n]==2 && s[y+1]==2 && s[y-1]==2) || !sum[n]){
            while(cnt<n-1){
                ans[++cnt]=1;
            }
        }
        else if(x==1){
            sol1();
        }
        else{
            for(i=n;i;i--){
                if(!s[i]){
                    x=i;
                    break;
                }
            }
            for(i=x-1;i;i--){
                if(!s[i]){
                    k=i;
                    break;
                }
            }
            if(sum[n]-sum[k]==2 && s[x+1]==2 && s[x-1]==2){
                for(i=1;i<k-1;i++){
                    ans[++cnt]=1;
                    get(i);
                }
                if(k==1 || !s[k-1]){
                    if(k>1){
                        ans[++cnt]=1;
                    }
                    for(i=k+1;i<x-1;i++){
                        ans[++cnt]=2;
                    }
                    ans[++cnt]=1;
                    ans[++cnt]=2;
                }
                else if(s[k-1]==1){
                    for(i=k+1;i<x-1;i++){
                        ans[++cnt]=3;
                    }
                    ans[++cnt]=2;
                    ans[++cnt]=1;
                    ans[++cnt]=2;
                }
                else{
                    if(s[k+1]==1){
                        ans[++cnt]=2;
                        for(i=k;i<x-1;i++){
                            ans[++cnt]=1;
                        }
                        ans[++cnt]=2;
                    }
                    else{
                        for(i=k+1;i<x-1;i++){
                            ans[++cnt]=3;
                        }
                        ans[++cnt]=2;
                        ans[++cnt]=2;
                    }
                }
            }
            else{
                for(i=1;i<k;i++){
                    ans[++cnt]=1;
                    get(i);
                }
                if(!s[k]){
                    if(sum[n]-sum[k]==3 && k+1<x-1 && s[k+1]==2 && s[x-1]==2 && s[x+1]==2){
                        for(i=k+1;i<x-1;i++){
                            ans[++cnt]=2;
                        }
                        ans[++cnt]=1;
                        ans[++cnt]=2;
                        while(cnt<n-1){
                            ans[++cnt]=1;
                        }
                    }
                    else{
                        ans[++cnt]=1;
                        get(k++);
                    }
                }
                if(cnt<n-1){
                    for(i=k;i<=n;i++){
                        s[i-k+1]=s[i];
                    }
                    n=n-k+1;
                    sol1();
                }
            }
        }
        for(n=r;cnt<n-1;){
            ans[++cnt]=1;
        }
        while(cnt){
            ans[0]+=ans[cnt]*pw[n-1-cnt];
            cnt--;
        }
        cout<<ans[0]<<endl;
    }
    return 0;
}

标签:右边,ver,int,可以,IMAWANOKIWA,S5,消掉,答案,操作
From: https://www.cnblogs.com/XichenOC/p/18682397

相关文章

  • 国产编辑器EverEdit - 部分编辑
    1部分编辑1.1应用场景  在编辑部分重要文档时,为了防止改错重要数据,将编辑区域限制在一个很小的区域是个不错的主意。1.2使用方法步骤1:使用鼠标或键盘选择需要编辑的区域。步骤2:选择菜单编辑->部分编辑或使用快捷键Alt+]打开部分编辑功能。注:打开“部分编辑”......
  • 【大屏可视化】系统(Vue3 + ECharts5)快速实现和应用 ️
    ......
  • Quantum computing for the very curious——Part I: The state of a qubit
    NOTEQuantumcomputingfortheverycuriousPrefacequbitisshortofthequantumbit,whereasthestateofabitisanumber(0or1),thestateofaqubitisavectorinatwo-dimensionalvectorspaceMaybethestateofthequbitisbeingstoredsomehow......
  • 请写出:link、:visited、:hover、:active的执行顺序
    在CSS中,:link、:visited、:hover、:active是四种伪类选择器,它们通常用于定义超链接(<a>标签)在不同状态下的样式。这些状态的选择器有一个特定的顺序,通常被称为“LoVe/HAte”顺序,这是由它们各自代表的状态和这些状态通常发生的顺序来确定的。:link-选择所有未被访问的链接。:......
  • DBeaver 22.0 最新版下载及安装教程
    DBeaver简介DBeaver是一个通用的数据库管理工具和SQL客户端,支持MySQL,PostgreSQL,Oracle,DB2,MSSQL,Sybase,Mimer,HSQLDB,Derby,以及其他兼容JDBC的数据库。DBeaver提供一个图形界面用来查看数据库结构、执行SQL查询和脚本,浏览和导出数据,处理BLOB/CLOB数据,修......
  • 【SQL Server】Service Broker——在单个数据库建完成对话
    一般来说,在SQLServer中调用存储过程,是同步的。如果一个操作比较长,那么我们我们希望执行异步操作。消息队列概念。消息队列在SQLServer李,是一种存储消息的结构。消息生产者将消息发送到队列中,而消息消费者则从队列中读取并处理消息。这种机制实现了应用程序组件之间的异步通信,......
  • web攻击-外部路径遍历攻击(External Path Traversal Attack)
    外部路径遍历攻击(ExternalPathTraversalAttack),也被称为目录遍历攻击,是一种网络攻击技术,攻击者试图通过篡改应用程序或系统的路径参数,访问本来应该受限的文件或目录。 这种攻击通常发生在Web应用程序中,当应用程序处理用户输入的文件路径时,如果没有对路径进行适当的验证和过......
  • 256点FFT处理器(verilog实现)
    1.设计功能与要求FFT用于快速计算离散傅立叶变换(DFT)。长为\(N\)的序列\(x(n)\)的DFT定义为:\[X(k)=\sum_{n=0}^{N-1}x(n)e^{-j2\pink/N}\]相应的序列\(X(k)\)的IDFT定义为\[x(n)=\sum_{n=0}^{N-1}X(k)e^{j2\pink/N}\]这里DFT和IDFT定义均忽略前面常数因子。这里设计......
  • 【一看就会】Autoware.universe的“规划”部分源码梳理【六】(behavior_path_planner第
    文章目录前言六、避障变道模块——autoware_behavior_path_avoidance_by_lane_change_module文件功能主次关系功能依赖说明核心文件-scene.cpp主要执行流程1.检查阶段2.数据更新阶段3.规划阶段辅助计算函数数据流向源码注释管理文件-manager.c......
  • 观察者(Observer)
    观察者模式定义对象间的一种一对多依赖关系,使得每当一个对象改变状态,则其相关依赖对象皆得到通知并被自动更新。Subject(目标)知道它的观察者,可以有多个观察者观察同一个目标;提供注册和删除观察者对象的接口。Observer(观察者)定义一个更新接口,在一个被观察对象改变时应被通知。......