1948.Educational Codeforces Round 163 - sol
202403
补题效率低下。
场上发挥并不是很好,
A ~ E 都是简单的,而场上没有去推 F 的式子,只是找了找规律,然后发现是一个不可做的东西就下播了。
如果直接推式子就会很快地做出来,还是非常可惜。
A. Special Characters
You are given an integer
. Your task is to build a string of uppercase Latin letters. There must be exactly
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
special characters in the AAABAACC string (at positions: , , , , and ). Print any suitable string or report that there is no such string.
。
直接 AABBAABBAA ……
即可。代码。
B. Array Fix
You are given an integer array
of length . You can perform the following operation any number of times (possibly zero): take any element of the array
, which is at least , 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
-rd element of the array , then the array becomes . - if we apply this operation to the
-nd element of the array , then the array becomes . Your task is to determine whether it is possible to make
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 in such a way that , where is the current length of the array .
有一个类 dp 的贪心做法吧。
首先最后一个数越小越优,所以我们直接记录前
C. Arrow Path
There is a grid, consisting of
rows and columns. The rows are numbered from to from top to bottom. The columns are numbered from to 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
. Every second, the following two actions happen one after another:
- Firstly, the robot moves left, right, down or up (it can't try to go outside the grid, and can't skip a move);
- 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
.
。
直接用某种图论最短路算法模拟即可。代码。
D. Tandem Repeats?
You are given a string
, 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
is a substring of a string if can be obtained from 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.
。
首先,枚举一下每一个长度是显然的,然后你就容易发现如果当前一半的长度为
于是你就可以做了,时间复杂度
E. Clique Partition
You are given two integers,
and . There is a graph on vertices, numbered from to , which initially has no edges. You have to assign each vertex an integer; let
be the integer on the vertex . All should be distinct integers from to . After assigning integers, for every pair of vertices
, you add an edge between them if . Your goal is to create a graph which can be partitioned into the minimum possible (for the given values of
and ) 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.
。
不要被数据小的东西误解了复杂度——这可能是给 checker 用的。
首先,很容易想到一定是一段一段地最优,
而我们容易猜到一个最长的长度就是
我也不知道。(实际上推一推也是好推的)
然后就到了这道题的关键之处——如何构造?
这里给出一种很好的做法——打表!!!
好,你做完了,稍微打一个表字典序最小的那个序列就有一些规律,很容易发现。
这样就线性做完了。代码。
F. Rare Coins
There are
bags numbered from to , the -th bag contains golden coins and silver coins. The value of a gold coin is
. The value of a silver coin is either or , determined for each silver coin independently ( with probability , with probability ). You have to answer
independent queries. Each query is the following:
— calculate the probability that the total value of coins in bags from to is strictly greater than the total value in all other bags.
。
组合数好题。
首先正常地想,对于银币,一共有
而这里,由于询问的是区间,我们把
现在来考虑每一次做的事情:
的差值是一定的,我们假设里面与外面的差值为 。 的差值是不定的,如果里面有 个被选成了 ,外面有 个选成 ,如果满足条件,则 。
这些东西能表明什么呢?
我们假设里面银币个数为
容易发现,如果直接把求和的区间改一下,就变成了一个没有系数的下指标求和,
《具体数学》上面声称了它没有封闭形式。
所以怎么办呢?
我们考虑换一个思路,对于这个式子,我们去枚举
由于
发现其实
而整个式子就相当于求一个后缀和,这是完全可以预处理出来的!!!
于是我们就做完了,只要预处理一下
代码实现是相当简单的,主要难点就在于转化去枚举差值。代码。
#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
vertices. Each edge of this graph has a weight; the weight of the edge connecting vertices and is (or if there is no edge between and ). All weights are positive integers. You are also given a positive integer
. You have to build a spanning tree of this graph; i. e. choose exactly
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
. Find any spanning tree with the minimum cost. Since the graph is connected, there exists at least one spanning tree.
。
简单题做不出来,降智哩。/kk
首先
而枚举什么呢?
枚举边集很明显是不合适的,而枚举点集又不好确定所选点的内部边,
所以我们考虑一种树上的方法——直接枚举点,每个点代表选择 它到它父亲 的边!!!
于是枚举了边集之后,发现构建 MST 就是非常简单的了,
因为一定不会有一条边连到都没选和都选了的点,这是简单的,稍微画一画图就知道了。
这样我们直接跑一次最小生成树就做完了,时间复杂度
#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
- 遇到一种思路不可求的问题我们可以尝试转化枚举方式,用
去进行枚举。(F) - 有关二进制枚举的题,分析怎么枚举更优!!!(G)
本文作者:H_W_Y
本文链接:https://www.cnblogs.com/H-W-Y/p/18083162/cf1948
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步