AtCoder Beginner Contest 465(abc465)做题记录
AtCoder Beginner Contest 465 做题记录
高考完也是终于开始复建了,希望上大学能成为acm大神
A - Supermajority
题面:
比较 \(A\) 和 \(\cfrac23B\)。
\(1\le A,B\le1000\)
题解:
无
复杂度 \(\Theta(1)\)
代码:
#include<cstdio>
int a,b;
int main(){
scanf("%d%d",&a,&b),puts(a*3>b*2?"Yes":"No");
}
B - Parking 2
题面:
区间 \([L,R)\) 的范围内权值为 \(x\),之外权值为 \(y\),求 \([A,B)\) 区间的权值。
\(1\le X,Y\le1000\),\(1\le L<R\le23\),\(1\le A<B\le23\)
题解:
数据范围小,直接枚举就行
复杂度 \(\Theta(1)\)
代码:
#include<cstdio>
int x,y,l,r,a,b,ans;
int main(){
for(scanf("%d%d%d%d%d%d",&x,&y,&l,&r,&a,&b);a<b;a++)ans+=a>=l&&a<r?x:y;
printf("%d",ans);
}
C - Reverse Permutation
题面:
初始有一个长度为 \(N\) 的序列 \(A=(1,2,\dots,n)\)。
长度为 \(N\) 的字符串 \(S\) 由 o 和 x 构成,表示 \(N\) 次操作。
\(S_k=\) o 时表示将序列的前 \(k\) 项逆序;
\(S_k=\) x 时表示不操作。
\(2\le N\le5\times10^5\)
题解:
直接文艺平衡树
可以发现从后往前讨论更简单。
每有一次逆序操作,也就意味着位置从最左边与最右边互换。
于是维护操作次数和左右边界。
复杂度 \(\Theta(N)\)
代码:
#include<cstdio>
const int N=500005;
int n,a[N],l,r;
char s[N];
bool flag;
int main(){
scanf("%d",&n),scanf("%s",s+1),l=1,r=n;
for(int i=n;i;i--)flag^=s[i]=='o',a[flag?l++:r--]=i;
for(int i=1;i<=n;i++)printf("%d ",a[i]);
}
D - X to Y
题面:
若 \(\left\lfloor\cfrac xK\right\rfloor=y\) 则 \(x\) 可以经过一次操作变换为 \(y\),且 \(y\) 可以经历一次操作变换为 \(x\)。
求 \(X\) 到 \(Y\) 的最小操作次数。
\(T\) 组数据。
\(1\le T\le2\times10^5\),\(0\le X,Y\le10^18\),\(2\le K\le10^18\)
算法:
容易想到这是一颗完全 \(K\) 叉树,节点间的距离可由 \(\text{lca}(X,Y)\) 得到。
那么直接暴力找 \(\text{lca}\) 即可。
取值范围为 \(M\),则复杂度 \(\Theta(T\log M)\)
代码:
#include<cstdio>
int T,res;
unsigned long long x,y,k;
int main(){
for(scanf("%d",&T);T--;printf("%d\n",res))for(scanf("%llu%llu%llu",&x,&y,&k),res=0;x^y;(x>y?x:y)/=k,res++);
}
E - Digit Circus
题面:
有多少个区间 \([1,N]\) 以内的整数 \(x\) 满足以下三个条件中的恰好一个条件:
- \(x\) 是 \(3\) 的倍数
- \(x\) 的十进制包含数字 \(3\)
- \(x\) 的十进制恰好用了三种数字
\(1\le N\le10^{500}\)
题解:
是一个很巧妙的数位DP啊
定义状态 \(f(pos,limit,S,mod3)\) 表示考虑了从高到低前 \(pos\) 位数,是否位于 \(N\) 的上界的真假为 \(limit\),选取的的数字种类集合为\(S\) ,除以 \(3\) 的余数为 \(mod3\) 的总方案数。
令 \(N\) 的第 \(i\) 位数为 \(s_i\),长度为 \(len\)。
则有状态转移方程如下:
边界条件为:
若 \(S\neq\emptyset\),
则 \(f(len+1,limit,S,mod3)=[[mod3=0]+[3\in S]+[\text{card}(S)=3]=1]\);
否则 \(f(len+1,limit,S,mod3)=0\)。
数位种数为 \(b\),则时间复杂度 \(\Theta(\log N\times 2^b)\)
代码:
#include<cstdio>
#include<cstring>
const int N=505,MOD=998244353;
char s[N];
int f[2][N][1030][3],len;
inline void Add(int&x,int y){if((x+=y)>=MOD)x-=MOD;}
int dfs(int pos,bool limit,int bit,int mod3){
if(pos>len)return bit&&(__builtin_popcount(bit)==3)+!!(bit&8)+(!mod3)==1?1:0;
int res=0;
if(~f[limit][pos][bit][mod3])return f[limit][pos][bit][mod3];
for(int sup=limit?s[pos]^48:9,i=sup;~i;i--)Add(res,dfs(pos+1,limit&&i==sup,bit||i?bit|(1<<i):0,(mod3+i)%3));
return f[limit][pos][bit][mod3]=res;
}
int main(){
return scanf("%s",s+1),len=strlen(s+1),memset(f,-1,sizeof(f)),printf("%d",dfs(1,1,0,0)),0;
}
剩下的题明天写完再改

浙公网安备 33010602011771号