A. Flip Flop Sum

能换 \(-1,-1\) 就换,不能能换 \(1,-1\) 或 \(-1,1\) 也可以,否则只能换 \(1,1\)。

B. The Forbidden Permutation

如果原序列一开始就是好的那就结束,否则尝试打破一边的不等号即可。

C. Flexible String

暴力搜索每一个字符是否在 \(S\) 当中。时间复杂度 \(O(n2^{|\Sigma|})\)

D. Flexible String Revisit

随机给 \(01\) 串取反,问变到全 \(0\) 的期望步数。

考虑 \(f_i\) 表示当前有 \(i\) 个 \(1\) 的期望步数。不难有:

\[f_0=0,f_i=\dfrac inf_{i-1}+\dfrac{n-i}n f_{i+1}+1
\]

我们假设 \(f_n=x\),我们可以把每一个 \(f\) 写成关于 \(x\) 的一次函数,推回到 \(f_0\) 时解出 \(x\) 即可。

给一段参考代码。

void init(){
// 求 p[n]
a[n]=1,b[n]=0;
for(int i=n;i>=1;i--){
// ip[i-1]=np[i]-(n-i)p[i+1]-n
a[i-1]=(n*a[i]%MOD-(n-i)*a[i+1]%MOD+MOD)%MOD*inv(i)%MOD;
b[i-1]=((n*b[i]%MOD-(n-i)*b[i+1]%MOD+MOD)%MOD-n+MOD)*inv(i)%MOD;
}
ll x=(MOD-b[0])*inv(a[0])%MOD;
for(int i=0;i<=n;i++)
p[i]=(a[i]*x+b[i])%MOD;
}

E. The Tree Has Fallen!

  • 给一棵点权树,每次询问查询以 \(r\) 为根时 \(u\) 的子树当中可选若干点权异或最大。
  • \(n,q\leq2\times 10^5\)。

首先这个问题显然时线性基,我们考虑对每个结点维护一个线性基存入他的子树点权。由于根可能被改变,所以需要换根。

更具体的,当我们把根从 \(u\) 换到 \(v\) 的时候,那么 \(v\) 的线性基就会变成全部元素的线性基,但是 \(u\) 的线性基会变成所有节点去除 \(v\) 节点的线性基的合并。但是线性基没有可减性,所以我们需要维护一个节点的相邻节点的前缀线性基,后缀线性基才可以完成转移。

代码写起来很丑,而且常熟巨大,当乐子看就好了。听说有 dfs 序的简单一点的代码,但是懒得打。

#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define ll long long
#define MP make_pair
const int MAXN=2e5+5;
int _;
struct Xxj{
int a[32];
}xxj[MAXN];
int ask(Xxj x){
ll res=0;
for(int i=31;i>=0;i--)
if((res&(1<<i))==0)
res^=x.a[i];
return res;
}
void insert(Xxj &x,int k){
for(int i=31;i>=0;i--)
if(!x.a[i]&&(k&(1<<i))){
x.a[i]=k;
return;
}else if(k&(1<<i))k^=x.a[i];
}
Xxj merge(Xxj x,Xxj y){
Xxj res=x;
for(int i=31;i>=0;i--)
if(y.a[i])
insert(res,y.a[i]);
return res;
}
void Clear(Xxj &x){
for(int i=31;i>=0;i--) x.a[i]=0;
}
vector<int> ve[MAXN];
vector<pair<int,int> > qe[MAXN];
int ans[MAXN];
int n,q,a[MAXN];
void dfs(int u,int fa){
insert(xxj[u],a[u]);
for(int v:ve[u]) if(v!=fa){
dfs(v,u);
xxj[u]=merge(xxj[u],xxj[v]);
}
}
void dfs_root(int u,int fa){
for(auto i:qe[u])
ans[i.second]=ask(xxj[i.first]);
int sz=ve[u].size();
vector<Xxj> pl(sz+1),pr(sz+1);
pl[0]=xxj[ve[u][0]];
pr[sz-1]=xxj[ve[u][sz-1]];Clear(pr[sz]);
for(int i=1;i<sz;i++)
pl[i]=merge(pl[i-1],xxj[ve[u][i]]);
for(int i=sz-2;i>=0;i--)
pr[i]=merge(pr[i+1],xxj[ve[u][i]]);
Xxj rt=xxj[u],copy;
for(int i=0;i<sz;i++)if(ve[u][i]!=fa){
if(!i) xxj[u]=pr[i+1];
else xxj[u]=merge(pl[i-1],pr[i+1]);
insert(xxj[u],a[u]);
copy=xxj[ve[u][i]],xxj[ve[u][i]]=rt;
dfs_root(ve[u][i],u);
xxj[ve[u][i]]=copy;
}
xxj[u]=rt;
return;
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++) ve[i].clear(),qe[i].clear(),Clear(xxj[i]);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
ve[u].push_back(v);
ve[v].push_back(u);
}
cin>>q;
for(int i=1;i<=q;i++){
int r,u;cin>>r>>u;
qe[r].push_back(MP(u,i));
}
dfs(1,0);
dfs_root(1,0);
for(int i=1;i<=q;i++)
cout<<ans[i]<<endl;
return;
}
int main(){
cin>>_;
while(_--)
solve();
}

F. Maximizing Root

  • 给一颗点权树(\(1\) 为根),每次可以选择一个未选择过的节点 \(u\) 然后把他的所有儿子点权乘上这颗子树所有节点点权的 \(\gcd\)。
  • 最多 \(k\) 次操作,最大化 \(1\) 的点权。
  • \(n\leq10^5,a_i\leq10^3\)。

显然操作肯定时自下而上的,也就是不会选择了一个祖先又选择了一个儿子。对于一次操作来说,变化的是一个子树的 \(\gcd\) 变成了它本身的平方。

考虑树形 dp。\(f_{i,j}\) 表示对 \(i\) 的子树,不操作根节点要所有权值都是 \(j\) 的倍数的最小操作数,容易得到转移:

\[f_{i,j}=\sum_{v\in son_i} \min(f_{v,j},(\min_{j|k^2} f_{v,k})+1)
\]

这个转移是 \(d(V)^2\) 的。总的时间复杂度时 \(O(n d^2(V))\),得以通过。

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e5+5;
const int MR=1005;
int f[MAXN][1005];// f[i][j] 表示 i 子树公约数 j 倍数最小操作数
vector<int> ve[MAXN],d[MR];
int tmp[1005],a[MAXN];
int n,k;
int gcd(int x,int y){
return (x%y==0)?y:gcd(y,x%y);
}
void dfs(int u,int fa){
for(int i:d[a[u]]) f[u][i]=0;
for(int v:ve[u])if(v!=fa){
dfs(v,u);
for(int p:d[a[v]]) if(f[v][p]!=1e9){
int g=gcd(a[u],p);
tmp[g]=min(tmp[g],f[v][p]);
g=gcd(a[u],p*p);
tmp[g]=min(tmp[g],f[v][p]+1);
}
for(int i:d[a[u]])
for(int j:d[i]) tmp[j]=min(tmp[j],tmp[i]);
for(int i:d[a[u]])
f[u][i]=min(f[u][i]+tmp[i],(int)1e9),tmp[i]=1e9;
}
return;
}
void solve(){
cin>>n>>k;
for(int i=1;i<=n;i++) ve[i].clear();
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
ve[u].push_back(v);
ve[v].push_back(u);
}
if(k==0){
cout<<a[1]<<endl;
return;
}
dfs(1,0);
int ans=0;
for(int i:d[a[1]])
if(f[1][i]<k) ans=max(ans,a[1]*i);
cout<<ans<<endl;
return;
}
int main(){
for(int i=1;i<MR;i++){
tmp[i]=1e9;
for(int j=i;j<MR;j+=i)
d[j].push_back(i);
}
int _;cin>>_;
while(_--) solve();
}

Codeforces Round #848 (Div. 2) A~F 题解的更多相关文章

  1. Codeforces Round #648 (Div. 2) A~F题解

    开始补cf了,还是记录一下,加深思路,打的应该都是div2.题面不截图了,直接说题意,思路,代码. A 题意:给一个01矩阵,两个人轮流填格子,仅当第i行,第j列全为0时才能填,不能填的人输,问谁赢? ...

  2. Codeforces Round #612 (Div. 2) 前四题题解

    这场比赛的出题人挺有意思,全部magic成了青色. 还有题目中的图片特别有趣. 晚上没打,开virtual contest打的,就会前三道,我太菜了. 最后看着题解补了第四道. 比赛传送门 A. An ...

  3. Codeforces Round #198 (Div. 2)A,B题解

    Codeforces Round #198 (Div. 2) 昨天看到奋斗群的群赛,好奇的去做了一下, 大概花了3个小时Ak,我大概可以退役了吧 那下面来稍微总结一下 A. The Wall Iahu ...

  4. Codeforces Round #573 (Div. 1) 差F

    Codeforces Round #573 (Div. 1) E 题意:二维平面上有 n 个点,你可以放至多 m 条直线使得 (0,0) 与每个点的连线至少与一条直线相交.求原点与所有直线的距离最小值 ...

  5. Codeforces Round #672 (Div. 2) A - C1题解

    [Codeforces Round #672 (Div. 2) A - C1 ] 题目链接# A. Cubes Sorting 思路: " If Wheatley needs more th ...

  6. Codeforces Round #532 (Div. 2):F. Ivan and Burgers(贪心+异或基)

    F. Ivan and Burgers 题目链接:https://codeforces.com/contest/1100/problem/F 题意: 给出n个数,然后有多个询问,每次回答询问所给出的区 ...

  7. Codeforces Round #611 (Div. 3) A-F简要题解

    contest链接:https://codeforces.com/contest/1283 A. Minutes Before the New Year 题意:给一个当前时间,输出离第二天差多少分钟 ...

  8. Codeforces Round #541 (Div. 2) (A~F)

    目录 Codeforces 1131 A.Sea Battle B.Draw! C.Birthday D.Gourmet choice(拓扑排序) E.String Multiplication(思路 ...

  9. Codeforces Round #198 (Div. 2)C,D题解

    接着是C,D的题解 C. Tourist Problem Iahub is a big fan of tourists. He wants to become a tourist himself, s ...

  10. Codeforces Round #615 (Div. 3) A-F简要题解

    contest链接:https://codeforces.com/contest/1294 A. 给出a.b.c三个数,从n中分配给a.b.c,问能否使得a = b = c.计算a,b,c三个数的差值 ...

随机推荐

  1. 从零开始配置 vim(13)——标签页插件

    原始的vim中标签页已经足够好用了.你完全可以使用原始 vim 提供的功能,但是使用插件可以让它更好看.这里我比较喜欢使用 bufferline 这个插件 安装 首先我们来安装它, 在使用 packe ...

  2. 20.5 OpenSSL 套接字RSA加密传输

    RSA算法同样可以用于加密传输,但此类加密算法虽然非常安全,但通常不会用于大量的数据传输,这是因为RSA算法加解密过程涉及大量的数学运算,尤其是模幂运算(即计算大数的幂模运算),这些运算对于计算机而言 ...

  3. grafana+prometheus+loki的使用

    grafana官网:https://grafana.com/zh-cn/grafana/ grafana下载:https://grafana.com/grafana/download?pg=graf& ...

  4. 使用Nuget快速集成.Net三维控件

    据老一辈的程序员说开发三维程序门槛很高,需要学若干年才能入门,自从遇上AnyCAD三维控件后,开发三维应用变的简单了.当结合nuget后,一切更简单了. 1 准备工作 安装VS201x以后,就可以开始 ...

  5. ntp.conf详解

    linux系统的ntp.conf文件默认保存在/etc/ntp.conf 版本: [root@dsview ntpstats]# cat /etc/redhat-release CentOS rele ...

  6. PostgreSQL-常用命令汇总

    1.连接到 PostgreSQL 数据库: psql -h 主机名/服务器IP -p 端口号 -U 用户名 -d 数据库名 注意:(1)在服务器上本地登录时,可以使用主机名或者本机IP地址进行登录,但 ...

  7. CF-926(已更新:B)

    CF-926 两点睡,七点起,阎王夸我好身体-- 主要这场实在是难绷,两个小时都在C题上吊死了,也不是没想过跳题,只是后面的题我更是一点思路都没有-^- "就喜欢这种被揭穿的感觉,爽!&qu ...

  8. NC51178 没有上司的舞会

    题目链接 题目 题目描述 Ural大学有N名职员,编号为1~N. 他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司. 每个职员有一个快乐指数,用整数 \(Hi\) 给出,其中 \(1\le ...

  9. 轻松玩转Makefile | 企业项目级Makefile实例

    前言 本文展示了一个比较完整的企业项目级别的Makefile文件,包括了:文件调用,源文件.头文件.库文件指定,软件版本号.宏定义,编译时间,自动目录等内容. 1.目录架构 本文中所采用的目录架构,在 ...

  10. Swoole从入门到入土(25)——多进程[进程间无锁计数器]

    Atomic 是 Swoole 底层提供的原子计数操作类,可以方便整数的无锁原子增减.原子计数器有如下特点: - 使用共享内存,可以在不同的进程之间操作计数 - 基于 gcc/clang 提供的 CP ...