AtCoder Beginner Contest 285 解题报告
AtCoder Beginner Contest 285 解题报告
\(\text{DaiRuiChen007}\)
A. Edge Checker 2
假设 \(a\ge b\),当且仅当 \(\left\lfloor\dfrac a2\right\rfloor=b\) 时成立
时间复杂度 \(\Theta(1)\)
#include<bits/stdc++.h>
using namespace std;
signed main() {
int a,b;
scanf("%d%d",&a,&b);
if(a<b) swap(a,b);
puts(a/2==b?"Yes":"No");
return 0;
}
B. Longest Uncommon Prefix
对于每个 \(i\) 从小到大不断增加 \(l\) 的值并判断即可
时间复杂度 \(\Theta(n^2)\)
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5001;
char s[MAXN];
signed main() {
int n;
scanf("%d%s",&n,s+1);
for(int i=1;i<n;++i) {
int l=0;
while(i+l+1<=n&&s[l+1]!=s[i+l+1]) ++l;
printf("%d\n",l);
}
return 0;
}
C. abc285_brutmhyhiizp
设 \(n=|S|\),字符串下标从 \(1\) 开始
从最高位开始考虑,假设最高位的字母是 \(\texttt C\),那么最高位填 \(\texttt A,\texttt B\) 或空的字符串一定更小,这样的字符串总数是 \(3\times 26^{n-1}\) 个,而最高位填 \(\texttt C\) 的串继续比较下一位即可
对于第二位、第三位……也类似统计即可
时间复杂度 \(\Theta(n)\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=20;
char s[MAXN];
signed main() {
int ans=0;
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=n,x=1;i>=1;--i,x*=26) ans+=(s[i]-'A'+1)*x;
printf("%lld\n",ans);
return 0;
}
D. Change Usernames
连接所有的 \(S_i\to T_i\),发现得到的图上每个点的出入度 \(\le 1\),因此这张图上只可能有若干个环和若干条链
注意到环一定不行,而链一定可行,因此对原图做拓扑排序判环即可
时间复杂度 \(\Theta(n\log n)\),瓶颈在用 map
实现字符串哈希上
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+1;
map <string,int> rec;
vector <int> G[MAXN];
int siz=0,deg[MAXN];
inline int id(string S) {
if(rec.find(S)==rec.end()) rec[S]=++siz;
return rec[S];
}
signed main() {
int n;
cin>>n;
for(int i=1;i<=n;++i) {
string u,v;
cin>>u>>v;
G[id(u)].push_back(id(v));
++deg[id(v)];
}
queue <int> q;
for(int i=1;i<=siz;++i) if(!deg[i]) q.push(i);
while(!q.empty()) {
int p=q.front(); q.pop();
for(int v:G[p]) {
--deg[v];
if(!deg[v]) q.push(v);
}
}
for(int i=1;i<=siz;++i) {
if(deg[i]>0) {
puts("No");
return 0;
}
}
puts("Yes");
return 0;
}
E. Work or Rest
考虑 dp,用 \(dp_i\) 表示前 \(i\) 天在第 \(i\) 天休息时的最大价值,状态转移方程如下:
\]
其中 \(\operatorname{cost}(l,r)\) 表示在 \(l,r\) 两天休息,中间不休息的情况下 \(l+1\sim r-1\) 获得的最大价值,通过前缀和优化可以在 \(\Theta(1)\) 的时间内计算
注意到第 \(n\) 天可能和下周的第一天结合产生贡献,为了解决这个问题,我们不妨把有休假的日子设为第 \(1\) 天,这样答案就是 \(dp_{n+1}\) 了
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=5005;
int a[MAXN],sum[MAXN],dp[MAXN];
inline int cost(int l,int r) {
int k=r-l-1;
return sum[(k+1)/2]+sum[k/2];
}
signed main() {
int n;
scanf("%lld",&n);
for(int i=1;i<=n;++i) {
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
memset(dp,-0x3f,sizeof(dp));
dp[1]=0;
for(int i=2;i<=n+1;++i) {
for(int j=1;j<i;++j) {
dp[i]=max(dp[i],dp[j]+cost(j,i));
}
}
printf("%lld\n",dp[n+1]);
return 0;
}
F. Substring of Sorted String
用 \(26\) 棵树状数组分别统计每个字母在特定区间中出现的次数
每次回答询问时先得到区间中的最小字母 \(lo\) 和最大字母 \(hi\),先判断字母 \(lo+1\sim hi-1\) 中的每个字母是不是都全部在 \([l,r]\) 中,然后简单模拟得到在每个字母对应的区间再判断这个区间是否全是该字母即可
时间复杂度 \(\Theta(|\Sigma|\times n\log n)\),\(\Sigma\) 为字符集
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
int n,q;
struct BitTree {
int tree[MAXN];
inline int lowbit(int x) { return x&-x; }
inline void Modify(int x,int v) {
for(;x<=n;x+=lowbit(x)) tree[x]+=v;
}
inline int q(int x) {
int ret=0;
for(;x;x-=lowbit(x)) ret+=tree[x];
return ret;
}
inline int Query(int l,int r) {
return q(r)-q(l-1);
}
} A[26];
char str[MAXN];
signed main() {
scanf("%d%s%d",&n,str+1,&q);
for(int i=1;i<=n;++i) {
A[str[i]-'a'].Modify(i,1);
}
while(q--) {
int op;
scanf("%d",&op);
if(op==1) {
int x; char c;
scanf("%d %c",&x,&c);
A[str[x]-'a'].Modify(x,-1);
str[x]=c;
A[str[x]-'a'].Modify(x,1);
} else {
bool ok=true;
int l,r;
scanf("%d%d",&l,&r);
int lo=26,hi=0;
for(int i=0;i<26;++i) {
if(A[i].Query(l,r)>0) {
lo=min(lo,i),hi=max(hi,i);
}
}
int x=l;
for(int i=lo;i<=hi;++i) {
int k=A[i].Query(l,r);
if(lo<i&&i<hi) if(k<A[i].Query(1,n)) ok=false;
if(A[i].Query(x,x+k-1)!=k) ok=false;
x+=k;
}
puts(ok?"Yes":"No");
}
}
}
G. Tatami
用 \(1\times 2\) 骨牌覆盖网格图立刻想到黑白染色建立二分图,对于已经被 \(1\times 1\) 覆盖的方格先删除,我们只需要为所有 \(c_{i,j}=2\) 的位置找到匹配即可,剩下的位置用 \(1\times 1\) 填补
正解好像是网络流,这里只提供一种乱搞做法:
对于每个 \(c_{i,j}=2\) 的没有匹配的点,直接在二分图上暴力搜出增广路,如果搜不出来增广路则输出 No
时间复杂度 \(\Theta(h^2w^2)\)
注意到实际上很难卡满时间复杂度,因此注意一下实现的常数(例如用时间戳标记对此复用 vis[]
数组避免过多的 memset
操作)即可通过本题
#include<bits/stdc++.h>
using namespace std;
const int MAXN=301,MAXV=1e5+1;
vector <int> G[MAXV];
int tar[MAXV],vis[MAXV];
inline bool dfs(int x,int t) {
if(vis[x]==t) return false;
vis[x]=t;
for(int p:G[x]) {
if(vis[p]==t) continue;
vis[p]=t;
if(tar[p]==-1||dfs(tar[p],t)) {
tar[p]=x,tar[x]=p;
return true;
}
}
return false;
}
const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
char a[MAXN][MAXN];
int id[MAXN][MAXN];
signed main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%s",a[i]+1);
for(int i=1,cnt=0;i<=n;++i) {
for(int j=1;j<=m;++j) {
id[i][j]=++cnt;
}
}
for(int i=1;i<=n;++i) {
for(int j=1;j<=m;++j) {
if(a[i][j]=='1'||(i+j)%2==0) continue;
for(int k:{0,1,2,3}) {
int x=i+dx[k],y=j+dy[k];
if(x<1||x>n||y<1||y>m) continue;
if(a[x][y]=='1') continue;
G[id[i][j]].push_back(id[x][y]);
G[id[x][y]].push_back(id[i][j]);
}
}
}
memset(tar,-1,sizeof(tar));
for(int i=1;i<=n;++i) {
for(int j=1;j<=m;++j){
if(a[i][j]=='2') {
if(tar[id[i][j]]!=-1) continue;
if(!dfs(id[i][j],id[i][j])) {
puts("No");
return 0;
}
}
}
}
puts("Yes");
return 0;
}
Ex. Avoid Square Number
显然立刻想到容斥,记 \(S_i\) 为至少存在 \(i\) 个平方数的方案数,那么得到:
\]
那么原问题转化为求 \(S_i\),\(S_i\) 可以转化为对于每个质因数 \(p_j\),求出把 \(E_j\) 拆成至少 \(i\) 个偶数的方案数的总乘积
考虑一次性处理出对于所有 \(E_j\) 的答案,对使用质因子数量建立生成函数,即 \(F_i(x)=\sum_{k=0}^\infty x^k\times f_{i,k}\),其中 \(f_{i,k}\) 为把 \(k\) 拆成至少 \(i\) 个偶数的方案数,那么我们知道 \(S_i=\prod_{j=1}^n f_{i,E_j}\)
而 \(F_i(x)\) 的值也是一个非常经典的问题,推导形过程如下:
F_i(x)
&=(x^0+x^2+x^4+x^6+\cdots)^i\times(x^0+x^1+x^2+x^3+\cdots)^{n-i}\\[2ex]
&=\left(\dfrac{1}{1-x^2}\right)^i\times\left(\dfrac 1{1-x}\right)^{n-i}\\
&=\dfrac{1}{(1-x)^n\times (1+x)^i}
\end{aligned}
\]
注意到我们可以每次暴力卷积计算出 \(F_0(x)\),而每次转移 \(F_{i}(x)\to F_{i+1}(x)\) 只需要乘上 \((1+x)^{-1}=1-x+x^2-x^3+x^4\cdots\) 就可以得到下一个 \(F\)
设 \(w=\max_{i}^k\{E_i\}\),那么所有的多项式都只需要在 \(\bmod x^{w+1}\) 意义下进行
注意到乘 \(\dfrac 1{1-x}\) 等价于做前缀和,乘 \(\dfrac 1{1+x}\) 等价于做前缀差(不等于差分,可以自己推导一下),因此多项式操作的复杂度都是 \(\Theta(w)\)
求出 \(F_0(x)\) 的复杂度是 \(\Theta(nw)\),而接下来依次计算 \(F_1(x)\sim F_n(x)\) 的总复杂度也是 \(\Theta(nw)\),每次通过 \(F_i(x)\) 求 \(S_i\) 的复杂度是 \(\Theta(k)\),执行 \(n\) 次,而容斥的复杂度是 \(\Theta(n)\)
综上,时间复杂度为 \(\Theta(nw+nk)\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e4+1,MOD=1e9+7;
int n,k,E[MAXN],p[MAXN];
inline void sum(vector <int> &F) {
for(int i=1;i<MAXN;++i) F[i]=(F[i]+F[i-1])%MOD;
}
inline void del(vector <int> &F) {
for(int i=1;i<MAXN;++i) F[i]=(F[i]+MOD-F[i-1])%MOD;
}
int fac[MAXN],inv[MAXN];
inline int binom(int n,int m) {
return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
inline int ksm(int a,int b,int m=MOD) {
int ret=1;
while(b) {
if(b&1) ret=ret*a%m;
a=a*a%m;
b=b>>1;
}
return ret;
}
signed main() {
scanf("%lld%lld",&n,&k);
fac[0]=inv[0]=1;
for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i%MOD,inv[i]=ksm(fac[i],MOD-2);
for(int i=1;i<=k;++i) scanf("%lld",&E[i]);
vector <int> F(MAXN);
F[0]=1;
for(int i=1;i<=n;++i) sum(F);
for(int i=0;i<=n;++i) {
p[i]=1;
for(int j=1;j<=k;++j) p[i]=(p[i]*F[E[j]])%MOD;
del(F);
}
int ans=0;
for(int i=0,f=1;i<=n;++i,f*=-1) {
ans=(ans+MOD+f*binom(n,i)*p[i]%MOD)%MOD;
}
printf("%lld\n",ans);
return 0;
}
AtCoder Beginner Contest 285 解题报告的更多相关文章
- AtCoder Beginner Contest 122 解题报告
手速选手成功混进rated only里面的前30名,但是总排名就到110+了... A - Double Helix #include <bits/stdc++.h> #define ll ...
- AtCoder Beginner Contest 146解题报告
题目地址 https://atcoder.jp/contests/abc146/tasks 感觉没有什么有意思的题... 题解 A #include <bits/stdc++.h> usi ...
- Atcoder Beginner Contest 124 解题报告
心态爆炸.本来能全做出来的.但是由于双开了Comet oj一个比赛,写了ABC就去搞那个的B题 还被搞死了. 回来写了一会D就过了.可惜比赛已经结束了.真的是作死. A - Buttons #incl ...
- AtCoder Beginner Contest 118 解题报告
A - B +/- A #include <bits/stdc++.h> int main() { int a, b; std::cin >> a >> b; b ...
- AtCoder Beginner Contest 120 解题报告
为啥最近都没有arc啊... A - Favorite Sound #include <algorithm> #include <iostream> #include < ...
- AtCoder Beginner Contest 117 解题报告
果然abc都是手速场. 倒序开的qwq. D题因为忘记1e12二进制几位上界爆了一发. A - Entrance Examination 就是除一下就行了... 看样例猜题意系列. #include& ...
- AtCoder Beginner Contest 132 解题报告
前四题都好水.后面两道题好难. C Divide the Problems #include <cstdio> #include <algorithm> using names ...
- AtCoder Beginner Contest 129 解题报告
传送门 写了四个题就跑去打球了.第五题应该能肝出来的. A - Airplane #include <bits/stdc++.h> using namespace std; inline ...
- AtCoder Beginner Contest 127 解题报告
传送门 非常遗憾.当天晚上错过这一场.不过感觉也会掉分的吧.后面两题偏结论题,打了的话应该想不出来. A - Ferris Wheel #include <bits/stdc++.h> u ...
- AtCoder Beginner Contest 126 解题报告
突然6道题.有点慌.比赛写了五个.罚时爆炸.最后一个时间不太够+没敢写就放弃了. 两道题奇奇怪怪的WJ和20/20.今天的评测机是怎么了. A Changing a Character #includ ...
随机推荐
- C/S、B/S、Web的介绍(Web应用开发)
文章目录 1.C/S结构介绍 2.B/S结构介绍 3.Web介绍 3.1 .什么是web? 3.2 .Web的工作原理 3.3 客户端应用技术 3.4 服务端应用技术 1.C/S结构介绍 Client ...
- 知识图谱-生物信息学-医学顶刊论文(Bioinformatics-2021)-KG4SL:用于人类癌症综合致死率预测的知识图神经网络
5.(2021.7.12)Bioinformatics-KG4SL:用于人类癌症综合致死率预测的知识图神经网络 论文标题:KG4SL: knowledge graph neural network f ...
- 7.websocket收发消息
客户端主动向服务端发起websocket连接,服务端接收到连接后通过(握手) 客户端 websocket socket = new WebSocket('ws://127.0.0.1/ws/'); 服 ...
- MySQL 索引失效-模糊查询,最左匹配原则,OR条件等。
索引失效 介绍 索引失效就是我们明明在查询时的条件为索引列(包括自己新建的索引),但是索引不能起效,走的是全表扫描.explain 后可查看type=ALL. 这是为什么呢? 首先介绍有以下几种情况索 ...
- CF Round #829 题解 (Div. 2)
F 没看所以摆了 . 看拜月教教主 LHQ 在群里代打恰钱 /bx 目录 A. Technical Support (*800) B. Kevin and Permutation (*800) C. ...
- C#中的特性+反射
反射 反射指程序可以访问.检测和修改它本身状态或行为的一种能力. 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象. 您可以使用反射动态地创建类型的实例,将类型 ...
- webgl(three.js)3D光伏,3D太阳能能源,3D智慧光伏、光伏发电、清洁能源三维可视化解决方案——第十六课
序: 能源是文明和发展的重要保障,人类命运不可避开的话题,无论是战争还是发展,都有它存在的身影.从石器时代到现代文明,人类的能源应用在进步,也在面临能源枯竭的危机与恐惧,而开发与应用可再生能源才是解决 ...
- etcd定时任务脚本执行失败
etcd定时任务脚本执行失败 报错如下:etcdctl命令不存在 是因为在脚本中etcdctl命令没有写绝对路径,修改标记部分改成绝对路径 可以先获取路径然后改成绝对路径问题解决 which etcd ...
- pycharm系列---基本配置
自动加入头文件 # _*_ coding: utf-8 _*_ # @Time : ${DATE} ${TIME} # @Author : xiechunhui # @Version:V 0.1 # ...
- 达梦-DBLINK数据库链接
aliases: [达梦 DBlink] tags: [数据库,DM,Blog] link: date: 2022-09-06 说明:DM-Oracle指的是在DM中创建链接至Oracle的Dblin ...