【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\),则有答案为:

\[\begin{cases} 2x(x-1)&r=0\\ 2x(x-1)+2r-1&0<r\leq x\\ 2x(x-1)+2r-2&x<r \end{cases} \]

赛时代码
//#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\) 时无解,否则有解。

总答案为:

\[\sum_{i=1}^k\vert S_i\vert\operatorname{cost}(i) \]

显然的贪心是让 \(\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\)

最终构造得到的就是:

\[1,2,3,6,12,\cdots,3\times2^{n-3} \]

参考代码
//#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;
}
posted @ 2026-07-13 12:16  TH911  阅读(52)  评论(0)    收藏  举报