[题解]AtCoder Beginner Contest 400(ABC400) A~E

A - ABC400 Party

如果\(A\)整除\(400\)就输出\(\frac{400}{A}\),否则输出-1

时间复杂度\(O(1)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
signed main(){
	cin>>n;
	if(400%n==0) cout<<400/n;
	else cout<<-1;
	return 0;
}

B - Sum of Geometric Series

模拟即可,中途累加超过\(10^9\)就直接输出并结束。

时间复杂度\(O(\min(m,\log_n V))\),其中\(V=10^9\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k=1,ans;
signed main(){
	cin>>n>>m;
	m++;
	while(m--){
		ans+=k;
		k*=n;
		if(ans>1e9) break;
	}
	if(ans>1e9) cout<<"inf";
	else cout<<ans;
	return 0;
}

C - 2^a b^2

容易发现满足条件的数要么是偶完全平方数,要么是\(2\)倍的完全平方数

因此答案就是下面两项累加:

  • 偶完全平方数的数量:\(\frac{\lfloor\sqrt{n}\rfloor}{2}\)
  • \(2\)倍的完全平方数的数量:\(\lfloor\sqrt{\frac{n}{2}}\rfloor\)

时间复杂度\(O(\log n)\)

注意直接使用<cmath>中的sqrt()会产生误差导致WA,需要手写(才知道sqrt()的误差这么大)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int sq(int x){
	int l=0,r=1e9;
	while(l<r){
		int mid=(l+r+1)>>1;
		if(mid*mid>x) r=mid-1;
		else l=mid;
	}
	return l;
}
signed main(){
	cin>>n;
	int a=sq(n),b=sq(n/2);
	cout<<a/2+b<<"\n";
	return 0;
}

D - Takahashi the Wall Breaker

考虑转成图论问题求解。

将每个位置\((x,y)\)看做节点,向其上下左右\(1\sim 2\)步处,共\(8\)个位置\((x',y')\)分别建边。

如果\((x,y)\)\((x',y')\)中途(不包括\((x,y)\))没有经过墙壁,那么边权就是\(0\),否则边权就是\(1\)

最后,从起点到终点的最短路即为答案。

由于边权只有\(0\)\(1\),我们可以使用0-1 BFS来求解单源最短路。

时间复杂度\(O(V+E)=O(nm)\),其中\(V,E\)分别表示点数和边数。

点击查看代码
#include<bits/stdc++.h>
#define H 1010
#define N 1000010
#define M 16000010
using namespace std;
int n,m,sx,sy,tx,ty,idx,head[N],d[N];
struct edge{int nxt,to;bool w;}e[M];
deque<int> q;
bitset<N> vis;
int dx[8]{-2,-1,0,0,0,0,1,2};
int dy[8]{0,0,-2,-1,1,2,0,0};
string s[H];
int conv(int x,int y){return x*m+y+1;}
void add(int u,int v,bool w){
	e[++idx]={head[u],v,w};
	head[u]=idx;
}
void tadd(int x,int y,int xx,int yy){
	if(xx<0||yy<0||xx>=n||yy>=m) return;
	bool w=0;
	if(abs(xx-x)+abs(yy-y)==2) w|=(s[(xx+x)/2][(yy+y)/2]=='#');
	w|=(s[xx][yy]=='#');
	add(conv(x,y),conv(xx,yy),w);
}
void bfs(int s){
	d[s]=0,q.push_back(s);
	while(!q.empty()){
		int t=q.front();
		q.pop_front();
		if(vis[t]) continue;
		vis[t]=1;
		for(int i=head[t],v;i;i=e[i].nxt){
			v=e[i].to;
			if(d[t]+e[i].w>=d[v]) continue;
			d[v]=d[t]+e[i].w;
			if(e[i].w) q.push_back(v);
			else q.push_front(v);
		}
	}
}
signed main(){
	memset(d,0x3f,sizeof d);
	cin>>n>>m;
	for(int i=0;i<n;i++) cin>>s[i];
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++) for(int d=0;d<8;d++) tadd(i,j,i+dx[d],j+dy[d]);
	cin>>sx>>sy>>tx>>ty;
	bfs(conv(sx-1,sy-1));
	cout<<d[conv(tx-1,ty-1)]<<"\n";
	return 0;
}

赛时稍微想麻烦了,其实并不需要像我这样真的建图,仅需在BFS中现用现遍历即可。

E - Ringo's Favorite Numbers 3

由于每个质因数的次数都是偶数,所以满足条件的数\(a\)一定是平方数。

那么我们不妨直接枚举\(\sqrt{a}\),它需要满足:

  • \(\sqrt{a}\)恰有\(2\)个不同的质因数。

考虑怎么快速计算出\(O(\sqrt{a})=O(\sqrt{V})\approx 10^6\) 以内满足上述条件的数。

我们可以先筛出此范围内的素数,然后直接暴力枚举就好,并不会超时。

这是因为只要我们枚举的过程没有冗余遍历,那么根据质因数分解定理,枚举出的数一定不会重复,时间复杂度就是\(O(\sqrt{V})\)


我们可以用一个桶来记录枚举出的数,每次询问就找桶中的前一个枚举出的数,输出其平方即可。可以使用前缀和+二分在\(O(\log \sqrt{V})\)内解决。

总时间复杂度\(O(Q\log V+\sqrt{V})\),其中\(\log V\)是二分求平方根的复杂度。

这道题直接调用sqrt()不会WA,不过数大的时候(比如C题)还是建议手写。

点击查看代码

``cpp

include<bits/stdc++.h>

define int long long

define N 1000010

using namespace std;
int pri[N],idx,flg[N],q,a;
bitset npri;
void init(int n){//线性筛
for(int i=2;i<=n;i++){
if(!npri[i]) pri[++idx]=i;
for(int j=1;j<=idx;j++){
if(ipri[j]>n) break;
npri[i
pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}
int sq(int x){//开平方
int l=0,r=1e9;
while(l<r){
int mid=(l+r+1)>>1;
if(midmid>x) r=mid-1;
else l=mid;
}
return l;
}
signed main(){
init(1e6);
for(int i=1;i<idx;i++)
for(int j=i+1;pri[j]
pri[i]<=1e6;j++)
for(int k=pri[i]pri[j];k<=1e6;k=pri[i])
for(int l=k;l<=1e6;l=pri[j])
flg[l]=1;
for(int i=1;i<=1e6;i++) flg[i]+=flg[i-1];
cin>>q;
while(q--){
cin>>a;
a=sq(a);
a=lower_bound(flg+1,flg+1000001,flg[a])-flg;
cout<<a
a<<"\n";
}
return 0;
}

</details>
posted @ 2025-04-05 22:56  Sinktank  阅读(272)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.