Codeforces Round 596 题解
万幸的是终于碰上了一场上分好场。
不幸的是一开始差点不会 A。
万幸的是想了个不那么稳的结论过了 pretest。
不幸的是罚时很高,而且慌得一比。
万幸的是然后半个小时内把 B 和 C 码了。
不幸的是然后就只能看着排名一点一点掉了。
万幸的是最后 A 没被叉掉。
不幸的是我居然没敢去叉人。
万幸的是我就是叉了 10 个人排名也不会上涨超过 5。
不幸的是我每掉一名都会少涨两三分。
万幸的是我没去打隔壁的 ZR。
不幸的是我发现这场 ZR 我一题不会,打了就会掉分……
2A
没仔细想,但是应该分类讨论一下 \(d_a=d_b\),\(d_a+1=d_b\) 和 \(d_a=9,d_b=1\) 就行了。
2B1 & 2B2
没仔细想,但是感觉双指针,动态维护不同数的个数(开个 map)就行了。
2C/1A
先枚举要用多少个数拼成 \(n\)。假设当前枚举的是 \(i\)。
那么等价于用恰好 \(i\) 个 \(2\) 的整数次幂拼成 \(n-pi\)。
有解当且仅当 \(bitcnt(n-pi)\le i\) 且 \(n-pi\ge i\)。其中 \(bitcnt\) 是二进制表示中 \(1\) 的个数。
我当时猜的结论是如果有解答案不会超过 \(10^6\)(能稳就稳)。
搬运下官方题解:
当 \(n-30p\ge 30\) 时(即 \(i=30\) 时满足第二个条件),那么因为 \(n-30p<2^{30}\),\(30\) 是一定合法的。否则对于 \(i\ge 30\),\(n-pi\ge i\) 都不可能成立。所以答案至多是 \(30\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
char ch=getchar();ll x=0,f=0;
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int n,p;
inline int bitcnt(int x){
int c=0;
for(;x;x&=x-1) c++;
return c;
}
int main(){
n=read();p=read();
FOR(i,1,1000000){
if(n-p*i>=i && bitcnt(n-p*i)<=i){
printf("%d\n",i);return 0;
}
}
puts("-1");
}
2D/1B
把每个数质因数分解。设 \(a_i=p_{i,1}^{c_{i,1}}\times p_{i,2}^{c_{i,2}}\times\dots\times p_{i,l_i}^{c_{i,l_i}}\)。其中 \(p_{i,x}\) 均为质数且单调递增,\(c_{i,x}\) 均为正整数。
两个数 \(i,j\) 合法当且仅当 \(l_i=l_j\) 且 \(p_{i,x}=p_{j,x}\) 且 \(k|(c_{i,x}+c_{j,x})\)。
那么把 \((p_{i,x},c_{i,x}\bmod k)\) 这个二元组塞到一个 vector 后面。并且查找要求的 vector 之前的出现次数。
时间复杂度 \(O(nl\log n)\)。其中 \(l\) 为 \(n\) 以内所有正整数的互不相同质因子个数的最大值。\(n=10^5\) 时,\(l=6\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010,sq=333;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
char ch=getchar();ll x=0,f=0;
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int n,k,a[maxn];
vector<PII> d[maxn],tmp;
map<vector<PII>,int> cnt;
ll ans;
int main(){
n=read();k=read();
FOR(i,1,n) a[i]=read();
FOR(i,1,n){
int x=a[i];
tmp.clear();
FOR(j,2,sqrt(x)) if(x%j==0){
int cnt=0;
while(x%j==0) x/=j,cnt=(cnt+1)%k;
if(cnt) d[i].push_back(MP(j,cnt)),tmp.push_back(MP(j,k-cnt));
}
if(x>1) d[i].push_back(MP(x,1)),tmp.push_back(MP(x,k-1));
ans+=cnt[tmp];
cnt[d[i]]++;
}
printf("%lld\n",ans);
}
2E/1C
比较套路的一题。
令 \(f_{i,j,0}\) 表示目前在 \((i,j)\),上一步是从左边走过来的方案数。\(f_{i,j,1}\) 表示目前在 \((i,j)\),上一步是从上面走过来的方案数。
初始状态 \(f_{1,1,0}=f_{1,1,1}=1\)。答案是 \(f_{n,m,0}+f_{n,m,1}\)。(所以要特判 \(n=m=1\),至于初始状态为什么是这个,看到下面就知道了)
以 \(f_{i,j,0}\) 为例,枚举上一个是从上面走过来的点 \((i,k)\)。注意到 \((i,k)\) 右边的石头肯定之前都没被动过。
那么从 \((i,k)\) 走到 \((i,j)\) 当且仅当 \((i,k)\) 右边的石头个数 \(\le n-j\)。这样子这些石头都可以塞到 \((i,j)\) 右边,否则 \((i,j)\) 肯定被石头挡住。
如果这样,\(f_{i,j,0}+=f_{i,k,1}\)。
发现 \(k\) 一定是 \([l,j-1]\) 这么一段,可以二分 \(l\) 然后用前缀和优化。当然发现随着 \(j\) 递增,\(l\) 不会变小,也可以维护一个指针。我比较懒就用了二分。
时间复杂度 \(O(nm(\log n+\log m))\) 或者 \(O(nm)\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=2222,mod=1000000007;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
char ch=getchar();ll x=0,f=0;
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int n,m,f[maxn][maxn][2],rig[maxn][maxn],dn[maxn][maxn],sum1[maxn][maxn],sum2[maxn][maxn];
char mp[maxn];
bool bl[maxn][maxn];
int main(){
n=read();m=read();
if(n==1 && m==1) return puts("1"),0;
FOR(i,1,n){
scanf("%s",mp+1);
FOR(j,1,m) if(mp[j]=='R') bl[i][j]=true;
}
f[1][1][0]=f[1][1][1]=sum1[1][1]=sum2[1][1]=1;
FOR(i,1,n) ROF(j,m,1) rig[i][j]=rig[i][j+1]+bl[i][j+1];
ROF(i,n,1) FOR(j,1,m) dn[i][j]=dn[i+1][j]+bl[i+1][j];
FOR(i,1,n) FOR(j,1,m){
if(i==1 && j==1) continue;
int l=0,r=j;
while(l<r){
int mid=(l+r)>>1;
if(rig[i][mid]<=m-j) r=mid;
else l=mid+1;
}
if(l<j) f[i][j][0]=(f[i][j][0]+(sum1[i][j-1]-(l==0?0:sum1[i][l-1])+mod)%mod)%mod;
l=0;r=i;
while(l<r){
int mid=(l+r)>>1;
if(dn[mid][j]<=n-i) r=mid;
else l=mid+1;
}
if(l<i) f[i][j][1]=(f[i][j][1]+(sum2[i-1][j]-(l==0?0:sum2[l-1][j])+mod)%mod)%mod;
sum1[i][j]=(sum1[i][j-1]+f[i][j][1])%mod;
sum2[i][j]=(sum2[i-1][j]+f[i][j][0])%mod;
// printf("f[%d][%d]=%d\n",i,j,(f[i][j][0]+f[i][j][1])%mod);
}
printf("%d\n",(f[n][m][0]+f[n][m][1])%mod);
}
2F/1D
神仙题,这种构造永远想不到……
考虑逆操作,把一个点的兄弟变成它的父亲。
首先答案肯定不小于 \((n-1)-maxdep\)。因为每次操作树的最大深度最多增加 \(1\)。
然后发现一定可以构造一个方案使得答案就是 \((n-1)-maxdep\)。具体操作方法:找到一条从根开始的最长路径,找到上面随意一个有多个儿子的点 \(v\),取它在这条路径上的儿子 \(u\) 和任意另一个儿子 \(w\),把 \(w\) 变成 \(u\) 的父亲。可以发现最长路径一定变长了 \(1\)。
具体实现,每次取满足条件的最深的 \(u\)(注意,不是 \(v\))。可以发现每次操作之后,新的 \(u\) 一定是原来的 \(u\) 或者它的祖先。
时间复杂度 \(O(n\log n)\)。可以做到 \(O(n)\),但是好像很难写。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010,mod=998244353;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int n,fa[maxn],dep[maxn],last=1,chg,ans[maxn],al,seq[maxn],sl;
set<int> s[maxn];
int main(){
n=read();
FOR(i,2,n){
dep[i]=dep[fa[i]=read()+1]+1;
s[fa[i]].insert(i);
if(dep[i]>dep[last]) last=i;
}
chg=last;
while(chg!=1){
while(chg!=1 && s[fa[chg]].size()==1) chg=fa[chg];
if(chg!=1){
int was=fa[chg];
set<int>::iterator hhh=s[was].find(chg);
for(set<int>::iterator it=s[was].begin();it!=s[was].end();it++){
int f=*it;
if(f==chg) continue;
s[f].insert(chg);
fa[chg]=f;
ans[++al]=chg-1;
s[was].erase(hhh);
break;
}
}
}
for(int i=last;i;i=fa[i]) seq[++sl]=i-1;
ROF(i,n,1) printf("%d ",seq[i]);
printf("\n%d\n",al);
ROF(i,al,1) printf("%d ",ans[i]);
}
1E & 1F
这些都不会,咕了。
Codeforces Round 596 题解的更多相关文章
- Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2)
A - Forgetting Things 题意:给 \(a,b\) 两个数字的开头数字(1~9),求使得等式 \(a=b-1\) 成立的一组 \(a,b\) ,无解输出-1. 题解:很显然只有 \( ...
- Codeforces Round #556 题解
Codeforces Round #556 题解 Div.2 A Stock Arbitraging 傻逼题 Div.2 B Tiling Challenge 傻逼题 Div.1 A Prefix S ...
- Codeforces Round #569 题解
Codeforces Round #569 题解 CF1179A Valeriy and Deque 有一个双端队列,每次取队首两个值,将较小值移动到队尾,较大值位置不变.多组询问求第\(m\)次操作 ...
- Codeforces Round #557 题解【更完了】
Codeforces Round #557 题解 掉分快乐 CF1161A Hide and Seek Alice和Bob在玩捉♂迷♂藏,有\(n\)个格子,Bob会检查\(k\)次,第\(i\)次检 ...
- CFEducational Codeforces Round 66题解报告
CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第 ...
- Codeforces Round #542 题解
Codeforces Round #542 abstract I决策中的独立性, II联通块染色板子 IIIVoronoi diagram O(N^2 logN) VI环上距离分类讨论加取模,最值中的 ...
- Codeforces Round #596 Div1 A~E题解
我好菜啊 A 题意: 定义p-二进制数为2^k-p,给出n和p,求用最小个数的p-二进制数来表示n 1<=n<=10^9,-1000<=p<=1000 题解: 猜结论,答案不会 ...
- Educational Codeforces Round 19 题解【ABCDE】
A. k-Factorization 题意:给你一个n,问你这个数能否分割成k个大于1的数的乘积. 题解:因为n的取值范围很小,所以感觉dfs应该不会有很多种可能-- #include<bits ...
- Codeforces-Educational Codeforces Round 53题解
写之前,先发表下感慨:好久没写题解了,也许是因为自己越来越急利了,也可以说是因为越来越懒了. A. Diverse Substring 直接找一找有没有相邻的两个不同的字符即可. B. Vasya a ...
随机推荐
- fiddler教程:抓包带锁的怎么办?HTTPS抓包介绍。
点击上方↑↑↑蓝字[协议分析与还原]关注我们 " 介绍Fiddler的HTTPS抓包功能." 这里首先回答下标题中的疑问,fiddler抓包带锁的原因是HTTPS流量抓包功能开启, ...
- SQLSERVER预读逻辑读物理读
预读:用估计信息,去硬盘读取数据到缓存.预读100次,也就是估计将要从硬盘中读取了100页数据到缓存. 物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存再次去读硬盘.物理读10页,从硬盘中 ...
- python 爬虫 随机换user-agent
USER_AGENTS = [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like ...
- Github(第一次尝试)
重要提示:项目中的文件最好最好不要出现中文,尤其是复杂的中文文件名. 前提:本地已经用git 管理 一个测试项目(项目一),分支为master. 1.注册 github: http://git.osc ...
- Ubuntu18.04 卸载mysql5.7
查看MySQL的依赖项:dpkg --list|grep mysql 要删除上面的这些. 开始卸载: sudo apt-get autoremove --purge mysql-server sudo ...
- 【pat】C++之刷题常用STL容器整理
1.vector 动态数组,方便的动态扩容,方便的变量初始化(int类型默认初始化为0,bool默认初始化为false),可以用来实现邻接表(结点数太多的图). 头文件 #include<vec ...
- PalletOne调色板跨链的BTC实现
之前已经讲到了PalletOne调色板跨链以太坊ETH和ERC20的技术原理,接下来我们来讲解PalletOne跨链比特币BTC的技术原理. 一.BTC充币 假如用户A持有一定数量的比特币BTC,他希 ...
- mybatis无效比较:invalid comparison:java.util.data and java.lang.string
原因: 时间与空字符串比较是无效的,如果拿传入的时间类型参数与空字符串''进行对比则会引发invalid comparison:java.util.data and java.lang.string异 ...
- 手机分辨率DPI怎么计算
长度方向像素数平方加宽度方向像素平方然后开根号,最后除以屏幕大小(英寸)
- js写个小时钟
原生js写个小时钟 一.代码 今天美化博客园自学的哈,分享一下 <!--标题变成时钟--> <div id="Header1_HeaderTitle">&l ...