【LGR-290-Div.4】& ARC224 & CF2246
2026/7/12 打了三场比赛。
第一次 Rated 打 ARC。
上一次打 ARC 是受到 zt17 邀请,Unrated 打 ARC223。为了 Rated 打 ARC 在 7/11 打了 ABC466。
洛谷入门赛 #49
19:00~21:00
没什么好说的。打完了才发现等级分限制 \(1200\),我 \(1387\),不能涨等级分。
很快写完了,太简单了不放了。
AtCoder ARC224
20:00~22:00
A
猜测答案为 \(\mathcal O(1)\times k\),所以直接打了个暴力,过了。
容易发现 \(100k\) 是有 \(2\) 个连续零的,所以暴力增加的次数 \(\leq100\)。\(T\leq10^5\),可以通过。
赛时代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
int k;
bool check(ll ans){
bool zero=false;
do{
if(ans%10==0){
if(zero){
return true;
}
zero=true;
}else{
zero=false;
}
ans/=10;
}while(ans);
return false;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
cin>>k;
ll ans=k;
for(;!check(ans);ans+=k);
cout<<ans<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
B
手玩一下,发现最优构造就是把它尽量拼成一个正方形,多出来的就在右边和下面。因为你增加一个正方形,只会增加 \(1\sim 2\) 条共边。增加 \(3,4\) 条共边的可调整顺序变成每次增加 \(1,2\) 条边。
令 \(x=\left\lfloor\sqrt n\right\rfloor,r=n-x^2\),则有答案为:
赛时代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
ll n;
ll f(ll n){
ll x=sqrt((long double)n);
ll ans=2*x*(x-1);
ll r=n-x*x;
if(r==0){
return ans;
}else if(r<=x){
ans+=r*2-1;
}else{
ans+=r*2-2;
}
return ans;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
cin>>n;
cout<<f(n)<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
C
考虑如果是棵树,显然构造 \(a_x=a_{\operatorname{father}(x)}+1\) 即可。但是这是张图。
考虑类似于无向图 Tarjan 的 DFS 树,再构造 \(a_x=a_{\operatorname{father}(x)}+1\) 即可。DFS 过程中如果 \(a_x\) 有值就返回。
这样是正确的。考虑无向图 DFS 树只有树边和回溯边。回溯边可以丢掉不管, 因为树边已经满足了 \(x\) 能到达的节点 \(v\) 中有且仅有一个 \(v\) 满足 \(a_v=a_x-1\)。
回溯边肯定不会影响这个。
之后不同子树没有连边,互不影响。
赛时代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=3e5,M=3e5;
int n,a[N+1];
vector<int>g[N+1];
void dfs(int x,int fx){
if(a[x]||x==1){
return;
}
a[x]=a[fx]+1;
for(int v:g[x]){
dfs(v,x);
}
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
int m;
cin>>n>>m;
for(int i=1;i<=n;i++){
g[i].resize(0);
a[i]=0;
}
while(m--){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int v:g[1]){
dfs(v,1);
}
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
D
记 \(\operatorname{cost}(i)\) 为 \(i\) 的位数。
考虑「\(\forall 1\leq x<y\le k\),存在一张卡片,\(x,y\) 只出现了一个」这个条件不太好做,正难则反,不成立的条件是 \(x,y\) 都出现或都不出现。
设 \(S_x\subseteq\set{1,2,\cdots,n}\) 为写有 \(x\) 的卡片集。
则 \((x,y)\) 不合法的条件是 \(S_x=S_y\),合法的条件即 \(S_x\neq S_y\)。
把 \((x,y)\) 推广,即 \(S_1\neq S_2\neq\cdots\neq S_k\)。写有大于 \(k\) 的数字显然不优。
容易发现,最多有 \(2^n\) 种 \(S_i\),因此当 \(k>2^n\) 时无解,否则有解。
总答案为:
显然的贪心是让 \(\operatorname{cost}(i)\) 大的 \(\vert S_i\vert\) 尽可能小,因为 \(\operatorname{cost}(i)\) 是一定的。而 \(\operatorname{cost}(i)\) 单调不降,因此我们希望 \(i\) 越大的 \(\vert S_i\vert\) 越小。
\(S_i\) 的具体取值并不重要,我们只关心 \(\vert S_i\vert\) 的取值,考虑 \(\vert S_i\vert=x\) 的个数为 \(\dbinom nx\)。
因此 \(i\) 从 \(n\) 至 \(1\),依次分配 \(\dbinom n0\) 个 \(0\),\(\dbinom n1\) 个 \(1\),\(\dbinom n2\) 个 \(2\),直到 \(i=1\) 分配结束。
赛时代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
constexpr const int N=1e6,K=1e6,V=7;
int n,k,cnt[V+1];
int cost(int n){
int ans=0;
do{
ans++;
n/=10;
}while(n);
return ans;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
cin>>n>>k;
if(n<=20&&k>(1<<n)){
cout<<"-1\n";
continue;
}
ll ans=0,C=1,p=0,j=k;
for(int i=k;1<=i;i--){
ans+=cost(i)*p;
if(i==j){
C=C*(n-p)/(p+1);
p++;
j=i-C;
}
}
cout<<ans<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
/*
1
3 5
5
*/
E
赛时一直在写 D。然后还有 9min 的时候 zt17 问我怎么不写 E。
我写完 D 后还剩 7min,询问 zt17 7min 能不能写完 E。
他说他 4min 就写完了 /bx/bx。
然而我因为 switch 没写 break 被创飞了。赛后发现,被人机验证一直卡,最后加 break 就过了。
非常简单的发现不能删除的字符会把字符串分割成一个个部分。之后每次字符就贪心和前面匹配,不能匹配就清空前面的并记录答案。
栈模拟即可。
赛时代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
string s;
cin>>s;
vector<char>v;
int ans=0;
for(char ch:s){
switch(ch){
case 'A':
v.push_back('A');
break;
case 'B':
while(v.size()&&v.back()=='D'){
v.pop_back();
}
if(v.size()&&v.back()=='A'){
v.pop_back();
v.push_back('D');
}else{
v.resize(0);
ans++;
}
break;
case 'C':
while(v.size()&&v.back()=='A') {
v.pop_back();
}
if(v.size()&&v.back()=='D'){
v.pop_back();
}else{
v.resize(0);
ans++;
}
break;
}
}
cout<<ans<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
Codeforces Round 1108(Div.2)
A
一种直觉的构造是构造 \(p=\langle n,n-1,n-2,\cdots,1\rangle\)。
题目保证 \(n\) 为偶数,那么一定有一些性质。
此时 \(x_i\in S_i=\set{-i(n-i+1),0,i(n-i+1)}\)。注意到 \(x_i\) 对于答案的贡献一定为偶数(\(i\) 或 \(n-i+1\)),最终 \(\displaystyle\sum x_i\) 一定也是偶数,不为 \(1\)。
参考代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=50;
int n;
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
cin>>n;
for(int i=n;1<=i;i--){
cout<<i<<' ';
}
cout<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
B
\(n=1\) 时显然有解 \(a_1=1\)。
\(n=2\) 时,要求 \((a_1+a_2)\bmod a_1=(a_1+a_2)\bmod a_2=0\)。即 \(a_2\bmod a_1=0,a_1\bmod a_2=0\)。
有 \(a_1=\pm a_2\),但是要求 \(a_1,a_2\) 为互不相同正整数,矛盾,无解。
之后考虑 \(n\geq3\) 的情况。
因为 \(a_i\leq10^{17}\),因此指数增长是不能接受的,所以我们希望 \(a_1,a_2,\cdots,a_n\) 有很多相同的质因子。
考虑构造常数 \(k\) 使得 \(a_{i+1}=k\cdot a_i\),则需要满足 \(\displaystyle\sum_{j=1}^{i-1}a_j\bmod a_i=0\)。
尝试构造 \(k=2\),容易发现直接构造是不行的。因为不能保证 \(\displaystyle\sum_{j=1}^{i-1}a_j\bmod a_i=0\)。
最终构造得到的就是:
参考代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
constexpr const int N=50;
int n;
ll a[N+1];
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--){
cin>>n;
if(n==1){
cout<<"1\n";
}else if(n==2){
cout<<"-1\n";
}else{
a[1]=1;
a[2]=2;
a[3]=3;
for(int i=4;i<=n;i++){
a[i]=3*(1ll<<i-3);
}
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<'\n';
}
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
C
没看懂「non-decreasing」和 DeepSeek、CodeForces Better 翻译的「非递减」就是「单调不降」的意思,虚空思考 20min。
参考代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<map>
using namespace std;
#define int long long
constexpr const int N=2e5,P=1e9+7;
int n,a[N+1],fact[N+1];
int qpow(int base,int n){
int ans=1;
while(n){
if(n&1){
ans=1ll*base*ans%P;
}
base=1ll*base*base%P;
n>>=1;
}
return ans;
}
int C(int n,int m){
if(n<0||m<0||n<m){
return 0;
}
return 1ll*fact[n]*qpow(1ll*fact[m]*fact[n-m]%P,P-2)%P;
}
void pre(){
fact[0]=1;
for(int i=1;i<=N;i++){
fact[i]=1ll*fact[i-1]*i%P;
}
}
main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
pre();
int T;
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int k=0;
for(int i=n;1<=i;i--){
if(a[i]==-1){
k=i;
break;
}
}
int ansL[2]={1,0},ansR[2]={1,0};
for(int i=2;i<=k;i+=2){
ansL[0]=(ansL[0]+C(k,i))%P;
}
ansL[1]=(qpow(2,k)-ansL[0])%P;
map<int,int>cnt;
for(int i=k+1;i<=n;i++){
cnt[a[i]]++;
}
int p=1,q=0;
for(auto [x,y]:cnt){
p=1ll*p*qpow(2,y-1)%P;
if(cnt.count(x+1)){
q++;
}
}
ansR[0]=p;
ansR[1]=1ll*p*q%P;
int ans=(1ll*ansL[0]*ansR[0]%P+1ll*ansL[1]*ansR[1]%P)%P;
if(ans<0){
ans+=P;
}
cout<<ans<<'\n';
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}

浙公网安备 33010602011771号