首页 > 其他分享 >1948.Educational Codeforces Round 163 - sol

1948.Educational Codeforces Round 163 - sol

时间:2024-03-19 15:57:30浏览次数:31  
标签:1948 le int graph sum Educational sol 枚举 binom

202403

补题效率低下。


场上发挥并不是很好,

A ~ E 都是简单的,而场上没有去推 F 的式子,只是找了找规律,然后发现是一个不可做的东西就下播了。

如果直接推式子就会很快地做出来,还是非常可惜。


A. Special Characters

You are given an integer \(n\).

Your task is to build a string of uppercase Latin letters. There must be exactly \(n\) special characters in this string. Let's call a character special if it is equal to exactly one of its neighbors.

For example, there are \(6\) special characters in the AAABAACC string (at positions: \(1\), \(3\), \(5\), \(6\), \(7\) and \(8\)).

Print any suitable string or report that there is no such string.

\(1 \le n \le 50\)。

直接 AABBAABBAA …… 即可。代码


B. Array Fix

You are given an integer array \(a\) of length \(n\).

You can perform the following operation any number of times (possibly zero): take any element of the array \(a\), which is at least \(10\), delete it, and instead insert the digits that element consisted of in the same position, in order they appear in that element.

For example:

  • if we apply this operation to the \(3\)-rd element of the array \([12, 3, 45, 67]\), then the array becomes \([12, 3, 4, 5, 67]\).
  • if we apply this operation to the \(2\)-nd element of the array \([2, 10]\), then the array becomes \([2, 1, 0]\).

Your task is to determine whether it is possible to make \(a\) sorted in non-descending order using the aforementioned operation any number of times (possibly zero). In other words, you have to determine if it is possible to transform the array \(a\) in such a way that \(a_1 \le a_2 \le \dots \le a_k\), where \(k\) is the current length of the array \(a\).

\(2 \le n\)

有一个类 dp 的贪心做法吧。

首先最后一个数越小越优,所以我们直接记录前 \(i\) 个数满足条件,最后一个的值最小是多少就完成了。代码


C. Arrow Path

There is a grid, consisting of \(2\) rows and \(n\) columns. The rows are numbered from \(1\) to \(2\) from top to bottom. The columns are numbered from \(1\) to \(n\) from left to right. Each cell of the grid contains an arrow pointing either to the left or to the right. No arrow points outside the grid.

There is a robot that starts in a cell \((1, 1)\). Every second, the following two actions happen one after another:

  1. Firstly, the robot moves left, right, down or up (it can't try to go outside the grid, and can't skip a move);
  2. then it moves along the arrow that is placed in the current cell (the cell it ends up after its move).

Your task is to determine whether the robot can reach the cell \((2, n)\).

\(2 \le n \le 2 \times 10^5\)。

直接用某种图论最短路算法模拟即可。代码


D. Tandem Repeats?

You are given a string \(s\), consisting of lowercase Latin letters and/or question marks.

A tandem repeat is a string of an even length such that its first half is equal to its second half.

A string \(a\) is a substring of a string \(b\) if \(a\) can be obtained from \(b\) by the deletion of several (possibly, zero or all) characters from the beginning and several (possibly, zero or all) characters from the end.

Your goal is to replace each question mark with some lowercase Latin letter in such a way that the length of the longest substring that is a tandem repeat is maximum possible.

\(1 \le |S| \le 5000\)。

首先,枚举一下每一个长度是显然的,然后你就容易发现如果当前一半的长度为 \(k\),那么 \(i\) 和 \(i+k\) 相等的对数最大连续长度至少为 \(k\)。

于是你就可以做了,时间复杂度 \(\mathcal O(n^2)\)。代码


E. Clique Partition

You are given two integers, \(n\) and \(k\). There is a graph on \(n\) vertices, numbered from \(1\) to \(n\), which initially has no edges.

You have to assign each vertex an integer; let \(a_i\) be the integer on the vertex \(i\). All \(a_i\) should be distinct integers from \(1\) to \(n\).

After assigning integers, for every pair of vertices \((i, j)\), you add an edge between them if \(|i - j| + |a_i - a_j| \le k\).

Your goal is to create a graph which can be partitioned into the minimum possible (for the given values of \(n\) and \(k\)) number of cliques. Each vertex of the graph should belong to exactly one clique. Recall that a clique is a set of vertices such that every pair of vertices in it are connected with an edge.

Since BledDest hasn't really brushed his programming skills up, he can't solve the problem "given a graph, partition it into the minimum number of cliques". So we also ask you to print the partition itself.

\(2 \le n \le 40\)。

不要被数据小的东西误解了复杂度——这可能是给 checker 用的。


首先,很容易想到一定是一段一段地最优,

而我们容易猜到一个最长的长度就是 \(k\),为什么(你其实不需要知道)呢?

我也不知道。(实际上推一推也是好推的)

然后就到了这道题的关键之处——如何构造?

这里给出一种很好的做法——打表!!!

好,你做完了,稍微打一个表字典序最小的那个序列就有一些规律,很容易发现。

这样就线性做完了。代码


F. Rare Coins

There are \(n\) bags numbered from \(1\) to \(n\), the \(i\)-th bag contains \(a_i\) golden coins and \(b_i\) silver coins.

The value of a gold coin is \(1\). The value of a silver coin is either \(0\) or \(1\), determined for each silver coin independently (\(0\) with probability \(\frac{1}{2}\), \(1\) with probability \(\frac{1}{2}\)).

You have to answer \(q\) independent queries. Each query is the following:

  • \(l\) \(r\) — calculate the probability that the total value of coins in bags from \(l\) to \(r\) is strictly greater than the total value in all other bags.

\(1 \le n,q \le 3 \times 10^5,\sum a_i,\sum b_i \le 10^6\)。

组合数好题。


首先正常地想,对于银币,一共有 \(2^{b[n]}\) 种不同的情况,这是非常好理解的,每一个有两种情况嘛。

而这里,由于询问的是区间,我们把 \(a,b\) 两个数组都进行了前缀和的处理。

现在来考虑每一次做的事情:

  • \(a\) 的差值是一定的,我们假设里面与外面的差值为 \(c\)。
  • \(b\) 的差值是不定的,如果里面有 \(i\) 个被选成了 \(1\),外面有 \(j\) 个选成 \(1\),如果满足条件,则 \(j-i \lt c\)。

这些东西能表明什么呢?


我们假设里面银币个数为 \(A\),外面银币个数为 \(B\),则合法的方案数是:

\[\begin{align} & \displaystyle \sum_{i=0}^A \sum_{j=0}^B [j-i \lt c] \binom A i \binom B j \\ = & \displaystyle \sum_{i=0}^A \sum_{j=0}^B [i-j \gt -c] \binom A i \binom B j \end{align} \]

容易发现,如果直接把求和的区间改一下,就变成了一个没有系数的下指标求和,

《具体数学》上面声称了它没有封闭形式。

所以怎么办呢?


我们考虑换一个思路,对于这个式子,我们去枚举 \(i,j\) 的差值 \(d\),于是有了以下推导:

\[\begin{align} & \displaystyle \sum_{i=0}^A \sum_{j=0}^B [i-j \gt -c] \binom Ai \binom Bj \\ = & \displaystyle \sum_{d=-c+1} \sum_{j=0}^B \binom{A}{j+d} \binom Bj \end{align} \]

由于 \(A,B\) 是非负整数,所以我们可以使用对称公式,进一步就可以对后面的式子进行 范德蒙德卷积

\[\begin{align} = & \displaystyle \sum_{d=-c+1} \sum_{j=0}^B \binom{A}{j+d} \binom{B}{B-j} \\ = & \displaystyle \sum_{d=-c+1} \sum_{j} \binom{A}{j+d} \binom{B}{B-j} \\ = & \displaystyle \sum_{d=-c+1} \binom{A+B}{B+d} \\ = & \displaystyle \sum_{d=B-c+1} \binom {A+B}{d} \end{align} \]

发现其实 \(A+B\) 就是整个序列银币的个数,也就是前缀和处理后的 \(b[n]\),

而整个式子就相当于求一个后缀和,这是完全可以预处理出来的!!!


于是我们就做完了,只要预处理一下 \(\displaystyle \sum_{d} \binom{b[n]}{d}\) 的后缀和就可以完成了。

代码实现是相当简单的,主要难点就在于转化去枚举差值。代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int N=2e6+5;
int n,m,a[N],b[N];
ll fac[N],ifac[N],S[N],Inv;
const ll H=998244353;

ll binom(int n,int m){
  if(m<0||n<m) return 0;
  return fac[n]*ifac[m]%H*ifac[n-m]%H;
}

ll qpow(ll a,ll b){
  ll res=1;
  while(b){if(b&1) res=res*a%H;a=a*a%H,b>>=1;}
  return res;
}

ll calc(int c,int b){return S[max(0,b-c+1)]*Inv%H;}

int main(){
  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  cin>>n>>m;
  for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
  for(int i=1;i<=n;i++) cin>>b[i],b[i]+=b[i-1];
  
  Inv=qpow((H+1)/2,b[n]);
  fac[0]=1;
  for(int i=1;i<N;i++) fac[i]=1ll*fac[i-1]*i%H;
  ifac[N-1]=qpow(fac[N-1],H-2);
  for(int i=N-1;i>=1;i--) ifac[i-1]=1ll*ifac[i]*i%H;
  
  for(int i=N-2;i>=0;i--) S[i]=(binom(b[n],i)+S[i+1])%H;
  
  for(int i=1,l,r;i<=m;i++){
    cin>>l>>r;
    cout<<calc(a[r]-a[l-1]-(a[n]-a[r]+a[l-1]),b[n]-b[r]+b[l-1])<<' ';
  }
  return 0;
}

G. MST with Matching

You are given an undirected connected graph on \(n\) vertices. Each edge of this graph has a weight; the weight of the edge connecting vertices \(i\) and \(j\) is \(w_{i,j}\) (or \(w_{i,j} = 0\) if there is no edge between \(i\) and \(j\)). All weights are positive integers.

You are also given a positive integer \(c\).

You have to build a spanning tree of this graph; i. e. choose exactly \((n-1)\) edges of this graph in such a way that every vertex can be reached from every other vertex by traversing some of the chosen edges. The cost of the spanning tree is the sum of two values:

  • the sum of weights of all chosen edges;
  • the maximum matching in the spanning tree (i. e. the maximum size of a set of edges such that they all belong to the chosen spanning tree, and no vertex has more than one incident edge in this set), multiplied by the given integer \(c\).

Find any spanning tree with the minimum cost. Since the graph is connected, there exists at least one spanning tree.

\(1 \le n \le 20,1 \le c \le 10^6\)。

简单题做不出来,降智哩。/kk


首先 \(n\) 的范围很小,不难想到用二进制去直接枚举。

而枚举什么呢?

枚举边集很明显是不合适的,而枚举点集又不好确定所选点的内部边,

所以我们考虑一种树上的方法——直接枚举点,每个点代表选择 它到它父亲 的边!!!


于是枚举了边集之后,发现构建 MST 就是非常简单的了,

因为一定不会有一条边连到都没选和都选了的点,这是简单的,稍微画一画图就知道了。

这样我们直接跑一次最小生成树就做完了,时间复杂度 \(\mathcal O(2^nn^2)\)。代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back

const int N=1e3+3;
int n,m,fa[N],cnt;
ll ans=4e18,c,res;

struct edge{
  int u,v;
  ll w;
  edge(int A=0,int B=0,ll C=0){u=A,v=B,w=C;}
  bool operator <(const edge &a) const{return w<a.w;}
};
vector<edge> G;

int find(int x){
  if(x==fa[x]) return x;
  return fa[x]=find(fa[x]);
}

void merge(int u,int v){
  u=find(u),v=find(v);
  if(u!=v) fa[u]=v;
}

int main(){
  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  cin>>n>>c;
  for(int i=1;i<=n;i++)
    for(int j=1,w;j<=n;j++){
      cin>>w;
      if(w&&i<j) G.pb(edge(i,j,w));
    }
  sort(G.begin(),G.end());
  
  for(int s=0;s<(1<<n);s++){
    cnt=res=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(auto i:G)
      if( (((s>>(i.u-1))&1)||((s>>(i.v-1))&1)) && find(i.u)!=find(i.v)){
        ++cnt,res+=i.w;
        merge(i.u,i.v);
      }
    if(cnt==n-1) ans=min(ans,res+__builtin_popcount(s)*c);
  }
  cout<<ans;
  return 0;
}

Conclusion

  1. 遇到一种思路不可求的问题我们可以尝试转化枚举方式,用 \(\Delta\) 去进行枚举。(F)
  2. 有关二进制枚举的题,分析怎么枚举更优!!!(G)

标签:1948,le,int,graph,sum,Educational,sol,枚举,binom
From: https://www.cnblogs.com/H-W-Y/p/18083162/cf1948

相关文章

  • 01-Solr
    Solr011.Solr简介Solr是基于ApacheLucene构建的用于搜索和分析的开源框架,提供搜索、高亮显示和文字解析等功能。Solr是一个JavaWeb项目,且内嵌Jetty服务器。Solr6之前是一个war包,需要放在Tomcat上运行。Solr8+,内嵌Jetty服务器,Solr8+的启动流程:通过批处理文件(Solr安装目录下bi......
  • 解决问题:java、mysql、docker、linux、redis、solr适合初级或者刚入门的大学生
    java、mysql、redis、linux、docker中的问题Java问题解决,idea问题解决调试,服务器问题解决,项目部署,项目调试linux服务器上的安装以及运行环境的部署docker的部署可做技术栈:java开发:javaweb,jsp,servlet,javase,spring,springboot,ssm服务器:linux问题docker问题,To......
  • 修改 /etc/resolv.conf
    修改/etc/resolv.conf/etc/resolv.conf是Linux系统中用于配置DNS解析器的文件。确认systemd-resolved或NetworkManager服务是否仍在管理DNS设置检查systemd-resolved服务的状态:systemctlstatussystemd-resolved如果服务正在运行,你会看到active(running)......
  • CF1948
    A题意:定义一个字符是特殊的,当且仅当它左右两边恰有一个字符与之相同。要求构造一个字符串,使得恰好有\(n\)个特殊字符,或判断无解。考虑一个连续的字符段,如果长度\(1\),不贡献特殊字符;否则必然贡献\(2\)个。所以无解条件就是\(2\not\midn\)。否则可以用AABAABAABAAB.........
  • Python - 安装依赖包,发现与其他包版本冲突 ResolutionImpossible
    问题表现Tofixthisyoucouldtryto:1.loosentherangeofpackageversionsyou'vespecified2.removepackageversionstoallowpipattempttosolvethedependencyconflictERROR:ResolutionImpossibleERROR:Cannotinstalltensorboard==1.10.0,tens......
  • qmsolve包绘制自由微观粒子波函数的时间演化
            qmsolve包可以将薛定谔方程可视化,下面介绍一下一维自由微观粒子的薛定谔方程解。importnumpyasnpfromqmsolveimportHamiltonian,SingleParticle,TimeSimulation,init_visualization,femtoseconds,m_e,Å#定义势能项为零defpotential_barrier......
  • XOR Break — Solo Version
    题意思路最多两步解决1.一步:只要满足((n^m)<n)即可一步,只要在第一个mi=1的地方n也有1无论如何都可以随便改n得到m2.无解的情况:只要在第一个mi=1的时候n(i)->n(最高位-1)没有1出现肯定无法解决3.二步:类似于10110->0000110110->10101->00001只需......
  • Codeforces 1948G MST with Matching
    因为贡献是两个之和,考虑固定下一个,求解另一个的最优。\(\text{MST}\)似乎找不到什么好的办法固定,便考虑固定下最大匹配。对于树的最大匹配,考虑到因为树也是二分图,所以树的最大匹配\(=\)最小点覆盖。考虑如果知道了最小点覆盖内的点,那就说明如果一条边两个端点都不在点集中,是......
  • Educational Codeforces Round 163 A-E
    A.SpecialCharacters构造。形如\(A\)和\(B\)这类单个字符构成的字符串对答案的贡献为\(0\),而\(AA\)和\(AAAA\)这类多个相同字符构成的字符串对答案的贡献固定为\(2\)​,则无法构造出奇数值,由第二类字符串拼接即可构造出偶数值。时间复杂度:\(O(n)\)。#include<bit......
  • Codeforces 1948E Clique Partition
    考虑到有\(|i-j|\),所以肯定是让相邻的一部分在一个团里。考虑构造出一个最长长度的,后面类似复制几遍即可。考虑到\(|k-1|=k-1\),且因为\(a_i\)为一个排列,差的绝对值至少为\(1\),所以只考虑两端最长长度也只可能为\(k\)。不妨先假设最长长度为\(k\)来构造。那么......