10.06 国庆节第九场模拟赛

密钥(key)

Description

在这个问题中,一个密钥是指一个长度为\(3n\)的二进制序列,其中\(n\)是正整数。
序列的每一位从左往右依次被编号为\(1\)到\(3n\) ,一个密钥的权值是指数字不同的相邻位的个数再加上\(1\) 。比如:
\(000\) 的权值是 \(1\), \(011010100\) 的权值是 \(7\)。

密钥可以被修改。确切地说,你可以不断地进行下面的操作:任选两个相邻的位,然后同时将它们取反。例如,可以通过一次操作把 \(000\) 修改为 110 。

给定一个长度为\(3n\)的密钥,请通过不超过\(n\)次操作,将其修改为一个权值不少于\(2n\)的密钥。你可以认为合法方案必然存在。

Input

输入一行,包含一个长度为\(3\)的倍数的\(01\)序列。

Output

第一行包含一个整数\(m\),表示操作的次数,你需要保证\(0 \leq m \leq n\) 。

第二行包含\(m\)个正整数 \(a_1,a_2,\dots,a_m(1 \leq a_i < n)\),依次表示每次翻转第\(a_i\) 和第\(a_{i+1}\)位。

如果初始密钥的权值已经不小于\(2n\)你可以仅输出一行一个整数\(0\)。

xjb分析

玄学做法 \(50pts\)

? 考虑到对答案有贡献的情况为当前位置与下一位置字符不同.

我们\(O(n)\)枚举位置,判断当前位置\(i\)是否与下一位置\(i+1\)相同.

如果不同,我们可以尝试翻转这两个位置,但是想要对答案有贡献?我们需要再判断\(i\)位置与\(i+2\)位置与\(i-1\)的字符是否存在相同,再决定我们是否去变换这两个位置.

例如 :

我们这时候改变\(i\)位置,\(i+1\)位置的话,

这时候,对答案的贡献就会变多\(+1\)。

然后莫名其妙这样做就\(get\)了\(50pts\)

正解

看到\(3n\),我们考虑三个的情况.

存在这些情况.

  1. \(000\)  5.\(111\)
  2. \(001\)  6.\(110\)
  3. \(011\)  7.\(100\)
  4. \(010\)  8.\(101\)

我们发现,

\(2.6\)情况翻转中间位置可以使贡献更大.

\(3.7\)情况翻转最左边位置可以使贡献更大.

这个可以手试一下.

因此代码中简单地模拟一下即可 qwq。

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<string>
#include<cstring>
#define R register
using namespace std;
char s[300008];
int len,cnt,ans[300008],val;
int main()
{
//  freopen("key.in","r",stdin);
//  freopen("key.out","w",stdout);
    scanf("%s",s+1);
    len=strlen(s+1);
    for(R int i=1;i<=len;i++)
        if(s[i]!=s[i-1] and i!=1)
            val++;
    if((val+1)>=2*(len/3))
    {
        puts("0");
        exit(0);
    }
    for(R int i=1;i<=len-2;i+=3)
    {
        if(s[i]=='0' and s[i+1]=='0' and s[i+2]=='1')
        {
            ans[++cnt]=i+1;
            s[i+1]='1';s[i+2]='0';
        }
        if(s[i]=='0' and s[i+1]=='1' and s[i+2]=='1')
        {
            ans[++cnt]=i;
            s[i]='1';s[i+1]='0';
        }
        if(s[i]=='1' and s[i+1]=='1' and s[i+2]=='0')
        {
            ans[++cnt]=i+1;
            s[i+1]='0';s[i+2]='1';
        }
        if(s[i]=='1' and s[i+1]=='0' and s[i+2]=='0')
        {
            ans[++cnt]=i;
            s[i]='0';s[i+1]='1';
        }
        if(s[i]=='1' and s[i+1]=='1' and s[i+2]=='1')
        {
            if(i==1)ans[++cnt]=i;
            else if(s[i-1]=='1')
            {
                ans[++cnt]=i;
                s[i]='0';
                s[i+1]='0';
            }
            else ans[++cnt]=i+1,s[i+1]='0',s[i+2]='1';
        }
        if(s[i]=='0' and s[i+1]=='0' and s[i+2]=='0')
        {
            if(i==1)ans[++cnt]=i;
            else if(s[i-1]=='0')
            {
                ans[++cnt]=i;
                s[i]='1';
                s[i+1]='1';
            }
            else ans[++cnt]=i+1,s[i+1]='1',s[i+2]='0';
        }
    }
    printf("%d\n",cnt);
    for(R int i=1;i<=cnt;i++)
        printf("%d ",ans[i]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

最大公约数(gcd)

Description

Makik 是一名勤劳的学生。他在刚刚学完欧几里得算法时想多做一些练习题,于是在纸上写下了一个长度为\(n\)的排列。之后,他做了\(m\)轮练习。对于第\(i\)轮练习,他从排列中挑出一个区间\([l_i,r_i]\) ,并对处于这个区间中的元素两两求最大公约数,再找出这些最大公约数中的最大值。

Makik 已经成为最大公约数的大师了,而且仁慈地把这个练习方法介绍给了你。现在,请你也来做做看

Input

第一行包含两个数字\(n,m\),分别表示排列的长度和练习的轮数。
接下来一行\(n\)个数字,依次表示这个排列中的每个元素。
再接下来\(m\)行,其中第\(i\)行包含两个数字\(l_i,r_i\),表示在第\(i\)轮练习中挑出的区间。

Output

输出\(m\)行,每行一个数字,表示该轮练习里区间内的元素两两间最大公约数中的最大值。

xjb分析

暴力

 对于\(m\)次询问,直接枚举\([l_i,r_i]\)区间的数,两两求\(gcd\)取\(max\).

代码写法大致如下:

for(int i=1;i<=m;i++)
{
    scanf("%d%d",&l,&r);
    int now=0;
    for(int j=l;j<=r;j++)
        for(int k=j+1;k<=r;k++)
            now=max(now,gcd(a[j],a[k]));
}

时间复杂度为\(O(m\times n^2 loga_i)\)

令人感到mmp的是,暴力部分全部\(TLE\)。

正解

考虑到对答案有贡献的是这些数的约数.

因此我们对这些约数搞事。

做法

 对每个数求出约数,在一个区间内出现超过两次的约数,那么它肯定是某两个数的\(gcd\).

 这样我们把所有出现次数\(\geq 2\)的约数加入线段树中维护最大值,并每次更新即可.

但是,如果在线做的话依旧不行.

  我们考虑将询问离线.

如何离线?

 考虑到我们必须要知道整个区间的数的约数的情况,所以我们对询问的右端点排序.

我们从小到大对右端点\(r_i\)进行排序,当遇到某个右端点的时候,输出ans即可.

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cctype>
#define ls o<<1
#define rs o<<1|1
#define N 100005
#define R register
using namespace std;
inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
struct cod{
    int l,r,idx;
    bool operator <(const cod&a)const
    {
        return r<a.r;
    }
}que[100008];
int ans[N];
int n,m,a[N],tr[N<<3],exist[N];
inline void up(int o){tr[o]=max(tr[ls],tr[rs]);}
void build(R int o,R int l,R int r)
{
    if(l==r)
    {
        tr[o]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    up(o);
}
void change(int o,int l,int r,int pos,int del)
{
//  printf("%d %d %d %d %d",o,l,r,pos,del);
    if(l==r){tr[o]=max(tr[o],del);return;}
    int mid=(l+r)>>1;
    if(pos<=mid)change(ls,l,mid,pos,del);
    else change(rs,mid+1,r,pos,del);
    up(o);
}
int query(int o,int l,int r ,int x,int y)
{
//  printf("%d %d %d %d %d\n",o,l,r,x,y);
    if(x<=l and r<=y)return tr[o];
    int mid=(l+r)>>1,res=0;
    if(x<=mid)res=max(res,query(ls,l,mid,x,y));
    if(y>mid)res=max(res,query(rs,mid+1,r,x,y));
    return res;
}
int main()
{
 // freopen("gcd.in","r",stdin);
//  freopen("gcd.out","w",stdout);
    in(n),in(m);
    {
        for(R int i=1;i<=n;i++)in(a[i]);
        build(1,1,n);
        for(R int i=1;i<=m;i++)
            in(que[i].l),in(que[i].r),que[i].idx=i;
        sort(que+1,que+m+1);
        int now=1;
        for(R int i=1;i<=n;i++)
        {
            for(R int j=1;j*j<=a[i];j++)
            {
                if(a[i]%j==0)
                {
                    if(exist[j])change(1,1,n,exist[j],j);//判断之前是否存在过
                    if(exist[a[i]/j])change(1,1,n,exist[a[i]/j],a[i]/j);//判断之前是否存在过
                    exist[j]=i,exist[a[i]/j]=i;
                }
            }
            while(i==que[now].r and now<=m)
            {
                ans[que[now].idx]=query(1,1,n,que[now].l,que[now].r);
                now++;
            }
        }
        for(R int i=1;i<=m;i++)printf("%d\n",ans[i]);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

原文地址:https://www.cnblogs.com/-guz/p/9748068.html

时间: 2024-10-08 14:14:20

10.06 国庆节第九场模拟赛的相关文章

10-4国庆节第七场模拟赛题解

10-4 国庆节第七场模拟赛题解 T1工厂 (factory) 水 #include<iostream> #include<cstdio> #define int long long using namespace std; inline int read(){ int sum=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0

10-2国庆节第五场模拟赛题解

T1 seq: 序列2 (seq) Description 给定个长度为 n 的数列 {a},初始时数列中每个元素 a_i 都不大于 40.你可以在其上进行若干次操作.在一次操作中,你会选出相邻且相等的两个元素,并把他们合并成一个元素,新的元素值为 \((旧元素值+1)\). 请你找出,怎样的一系列操作可以让数列中的最大值变得尽可能地大?这个最大值是多少? Input 输入文件第一行一个正整数 n,表示数列的长度. 接下来一行 n 个不大于 40 的正整数,表示这个数列 {a }. Output

10-3国庆节第六场模拟赛题解

T1 炮 (cannon) Description Makik 曾经沉迷于打麻将,热衷于点炮的他近日终于开始爱上了中国象棋.面对一个n×m的棋盘,他不禁陷入了思考:在这张棋盘上摆"炮",并且任意两个"炮"之间不会互相攻击的方案数究竟有多少呢? 说明:两枚炮可以互相攻击,当且仅当它们处在同一行或同一列上且恰好间隔一枚棋子,即"炮打隔山". 由于 Makik 记不住太大的数字,所以请告诉他答案对 999983 取模的结果. Input 输入文件包含一

【一场模拟赛?】

JSH师兄来讲课,于是也弄了场比赛给我们做...被虐... A.简单的图论题 嗯求一个拓扑图中每个点的可达点数量,n=10000 嗯记忆化搜索,但是有可能搜到重复的点,于是我们不搜索可达点数量,转成搜索可达点集,这个可以用一个bool数组记录. 于是STL有某种东西叫做bitset(长知识 // Problem#: 14938 // Submission#: 3794800 // The source code is licensed under Creative Commons Attribu

2014.10.31我出的模拟赛【藏宝图】

藏宝图(treas.*) 背景 Czy爬上黑红树,到达了一个奇怪的地方…… 题目描述 Czy发现了一张奇怪的藏宝图.图上有n个点,m条无向边.已经标出了图中两两之间距离dist.但是czy知道,只有当图刚好又是一颗树的时候,这张藏宝图才是真的.如果藏宝图是真的,那么经过点x的边的边权平均数最大的那个x是藏着宝物的地方.请计算这是不是真的藏宝图,如果是真的藏宝之处在哪里. 格式 输入数据第一行一个数T,表示T组数据. 对于每组数据,第一行一个n,表示藏宝图上的点的个数. 接下来n行,每行n个数,表

2014.10.31我出的模拟赛【天神下凡】

天神下凡(god.*) 背景 Czy找到宝藏获得屠龙宝刀和神秘秘籍!现在他要去找经常ntr他的Jmars报仇…… 题目描述 Czy学会了一招“堕天一击”,他对一个地点发动堕天一击,地面上就会留下一个很大的圆坑.圆坑的周围一圈能量太过庞大,因此无法通过.所以每次czy发动技能都会把地面分割.Jmars拥有好大好大的土地,几十眼都望不到头,所以可以假设土地的大小是无限大.现在czy对他发动了猛烈的攻击,他想知道在泽宇攻击之后他的土地被切成几份了? Czy毕竟很虚,因此圆心都在x坐标轴上.另外,保证所

2014.10.31我出的模拟赛【挖掘机】

挖掘机(dig.*) 背景 附中机房谁最虚?高二一班***!感觉很顺,是吧? 题目描述 今天,丧尸czy开着挖掘机去上学(……).但是他发现他的mz满天下,所以一路上他碰到了好多他的mz.一开始他以1km/min的速度(=60km/h……)开着挖掘机前进.他发现他只会在恰好到达某一时刻或者到达某个距离遇到mz.每次遇到mz,czy都会毫不犹豫的把她们顺路捎走(^_^).但是他实在是太虚了,以至于当有i个mz时他的速度下降到1/(i+1).具体说,一开始czy以1km/min速度前进,有1个mz的

2014.10.31我出的模拟赛【黑红树】

黑红树(brtree.*) 背景 Mz们在czy的生日送他一个黑红树种子……czy种下种子,结果种子很快就长得飞快,它的枝干伸入空中看不见了…… 题目描述 Czy发现黑红树具有一些独特的性质. 1. 这是二叉树,除根节点外每个节点都有红与黑之间的一种颜色. 2. 每个节点的两个儿子节点都被染成恰好一个红色一个黑色. 3. 这棵树你是望不到头的(树的深度可以到无限大) 4. 黑红树上的高度这样定义:h(根节点)=0,h[son]=h[father]+1. Czy想从树根顺着树往上爬.他有p/q的概

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=