首页 > 其他分享 >Codeforces Gym 100958 E Cellular Automaton (Makoto rng_58 Soejima contest) 题解

Codeforces Gym 100958 E Cellular Automaton (Makoto rng_58 Soejima contest) 题解

时间:2022-11-17 15:25:57浏览次数:90  
标签:Makoto le 58 val int 题解 滑块 序列 define

题目链接

其实"序列中1的数量有限"是一个非常重要的条件。这意味着我们可以找到序列中的第一个1和最后一个1。

考虑这样一件事情:初始时我们把一个长度为\(2^{2w+1}\)的"滑块"放在刚好在第一个1前面的位置(这时滑块的内部全是0),然后每次把滑块向右移动一格(也就是删掉滑块的第一个字符,在末尾再加上一个),直到滑块移动到序列中最后一个1的右边为止。发现题目中的要求等价于:给每一种滑块的状态分配一个0或1的值,对于任意一个序列做出上面这种操作,序列中1的个数必须等于过程中经过的所有滑块状态的值之和。(这是关键观察)

可能的滑块状态有\(2^{2w+1}\)种,如果一个状态可以通过"向右移动一格"的操作变成另一个状态,我们就在这两个状态之间连有向边。给每条边赋一个权值,如果用这条边转移时在原滑块末尾加上的字符是1则把值赋为-1,否则赋为0。这时题目中的要求就转化为了:对于从"0000000..."(全0)走一圈回到"0000000..."的任意一条路径,它上面所有点和边的权值和为0。(仔细想一下)

而如果序列中的1数量无限,我们压根找不到第一个1和最后一个1,也就不能像这样思考了。

考虑怎么给每个点赋值才能满足上面说的条件。令"0000000..."代表的节点为s。首先对于任意节点i,从s走到i的任意一条路径权值和都是相等的,否则就不满足上面的条件(因为这张有向图显然是强连通的,任何一个点都能走回s)。令\(sum_i\)表示从s走到i的任意一条路径的权值和。发现对于每个到i直接有边的节点j,\(sum_j+EdgeValue_{i,j}\)都相等(为了满足上面的条件),令这个值为val。则\(val \le sum_i \le val+1\)。发现以上总结出的所有条件都是不等式的形式(a=b可以转化为\(a \ge b且a \le b\)),所以可以用差分约束。

由于题目要求的是字典序至少为S的答案,不妨先检查S是否合法。然后从后往前枚举答案最晚可以从哪一位开始与S不同。我们每次要干的事情相当于是:指定有向图中的一些点必须取0或者必须取1,其他的点随意,判断是否有解。只要把上面说的\(val \le sum_i \le val+1\)改一下就行了。

令\(N=2^{2w+1}\)。一共需要做\(O(N)\)次差分约束,每次复杂度为\(O(N^2)\),总复杂度\(O(N^3)\)。

点击查看代码
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back

void fileio()
{
  #ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  #endif
}
void termin()
{
  #ifdef LGS
  std::cout<<"\n\nPROGRAM TERMINATED";
  #endif
  exit(0);
}

using namespace std;

int w,dist[140],cnt[140],inq[140];
string s,ans="";
vector <pii> rg[140],g[140];
queue <int> q;

int relax(int x,int vv,int y)
{
  if(dist[x]>dist[y]+vv)
  {
    dist[x]=dist[y]+vv;
    cnt[x]=cnt[y]+1;
    if(cnt[x]>(1<<(w+w+1))+3) return -1;
    return 1;
  }
  else return 0;
}

bool spfa()
{
  rep(i,135) dist[i]=1e9,cnt[i]=inq[i]=0;
  dist[0]=0;inq[0]=1;q.push(0);
  while(!q.empty())
  {
    int f=q.front();q.pop();inq[f]=0;
    rep(i,g[f].size())
    {
      int val=relax(g[f][i].fi,g[f][i].se,f);
      if(val==-1) return false;
      if(val==1&&inq[g[f][i].fi]==0) q.push(g[f][i].fi),inq[g[f][i].fi]=1;
    }
  }
  return true;
}

bool check()
{
  rep(i,135) g[i].clear();
  rep(i,1<<(w+w+1))
  {
    for(int j=1;j<rg[i].size();++j)
    {
      int xa=rg[i][0].fi,xb=rg[i][j].fi,va=rg[i][0].se,vb=rg[i][j].se;
      g[xa].pb(mpr(xb,vb-va));g[xb].pb(mpr(xa,va-vb));
    }
    if(rg[i].size())
    {
      int xx=rg[i][0].fi,vv=rg[i][0].se,ll=0,rr=1;
      if(i<ans.size())
      {
        if(ans[i]=='0') rr=0;
        else ll=1;
      }
      g[i].pb(mpr(xx,vv-ll));g[xx].pb(mpr(i,rr-vv));
    }
  }
  return spfa();
}

int main()
{
  fileio();
  freopen("cell.in","r",stdin);
  freopen("cell.out","w",stdout);

  cin>>w>>s;
  
  rep(i,1<<(w+w+1))
  {
    rep(j,2)
    {
      int to=(i>>1)|(j<<(w+w));
      rg[to].pb(mpr(i,j));
    }
  }

  ans=s;if(check()){cout<<ans<<endl;termin();}
  for(int i=s.size()-1;i>=0;--i) if(s[i]=='0')
  {
    ans=s.substr(0,i);ans.pb('1');
    if(check())
    {
      while(ans.size()<s.size())
      {
        ans.pb('0');
        if(!check()) ans[ans.size()-1]='1';
      }
      cout<<ans<<endl;
      termin();
    }
  }
  puts("no");

  termin();
}

标签:Makoto,le,58,val,int,题解,滑块,序列,define
From: https://www.cnblogs.com/legendstane/p/codeforces-gym-100958-e-cellular-automaton-rng-58-co

相关文章

  • Kafka启动报错:/bin/kafka-run-class.sh: line 258: exec: java: not found
    Kafka启动报错处理:/opt/module/kafka/bin/kafka-run-class.sh:第258行:exec:java:未找到今天在安装kafka后启动的时候出现了报错:/software/kafka_2.11-0.11.0.0/bin......
  • CF707E Garlands 题解
    简要题意:在一个\(n\timesm\)的矩阵(\(n,m\le2000\))中,每个点都有个灯,刚开始所有灯都是亮的,每个灯都有一个颜色(\(k\le2000\))和一个权值,保证所有颜色相同的点是联通块。现......
  • UVA1331 题解
    前言题目传送门!更好的阅读体验?计算几何、区间DP。思路......
  • T292306 01最短路 题解
    又是一个找不到题目所以自己写的题。。。40迪杰斯特拉,但是搞不懂为什么是wa而不是re的#include<bits/stdc++.h>#definefor1(i,a,b)for(inti=a;i<=b;i++)#definell......
  • 紫罗兰题解
    题意概述给定一张\(n\)个顶点\(m\)条边的无向图,顶点的编号在\(1\simn\)内,第\(i\)条无向边连接着顶点\(x_i\)与\(y_i\)。我们称顶点\(v_0,v_2,\cdots,v_{k......
  • DTOJ 2022-11-15 测试 题解
    测试成果100+100+50+10=260还行吧(虽然T2做法很迷惑)A惊鸿(grace)DTOJP6367题面大意给定一个\(n\)行\(m\)列的仅包含小写字母的矩阵\(A\)。求从\((1,1)\)......
  • 长春花题解
    题意概述给定一个素数\(p\),对每个\(0\lex<p\),设\(f(x)\)表示一个最小的非负整数\(a\),使得存在一个非负整数\(b\),满足\((a^2+b^2)\bmodp=x\)。现在,你想要......
  • LeetCode 题解 1922. 统计好数字的数目
    1922.统计好数字的数目-力扣(Leetcode)题解思路一:快速幂#defineMOD1000000007longlongpower(intn,longlongtimes){if(times==1)returnn;if(ti......
  • 【问题解决】ESP32开发板上的CP210xUSB转串口坏了怎么办
        今天居然遇到了主板上的USB转串口芯片坏了的情况!这运气真是。。    还好问题解决了,心理舒服点,这里记录一下,以后大家要是遇到也可以参考。    先吐槽CP210x......
  • AI最前沿 | 重磅专题:类脑机器学习 问题解决器
    AI最前沿|重磅专题:类脑机器学习https://mp.weixin.qq.com/s/gUFb1wXV3QwWRPDaNESvjw子句级关系感知数学单词问题解决器Clause-levelRelationship-awareMathWordPr......