AtCoder Beginner Contest 280 题解

A - Pawn on a Grid

看样例猜题意(

要求的是 # 的数量,直接判断。

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
using namespace std;
int n,m,ans;
char c;
signed main(){
	IOS;TIE;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>c;
			if(c=='#') ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
}

B - Inverse Prefix Sum

看样例猜题意*2

直接输出差分数组就好了。

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
using namespace std;
int n,a[200005];
signed main(){
	IOS;TIE;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cout<<a[i]-a[i-1]<<' ';
	cout<<endl;
	return 0;
}

C - Extra Character

两个字符串第一个不同位置加一个一定是合法的。正确性显然。

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
using namespace std;
string s,t;
signed main(){
	IOS;TIE;
	cin>>s>>t;
	for(int i=0;i<t.size();i++){
		if(s[i]!=t[i]){
			cout<<i+1<<endl;
			return 0;
		}
	}
	return 0;
}

D - Factorial and Multiple

一开始傻掉萎了两发(

直接二分答案就好,二分答案为 x 的阶乘。

如何判断 x 是否合法?设 cntpi 为原来的 k 所含质因数 pi 的数量,显然需要 1x 中所有数分解质因数后每一个 pi 的数量之和都 >cntpi

考虑如何快速计算 1x 中各质因数数量之和。设要求的质因数为 pi,则 1x 中质因数 含一个及以上 pi 的数的数量为 xpi含两个及以上 pi 的数的数量为 xpi2含三个及以上 pi 的数的数量为 xpi3,以此类推。

然后就做完了。

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
using namespace std;
int k,n;
map<int,int> mp,mp2;
bool check(int mid){
	for(auto i:mp){
		int cnt=0,tmp=i.fi;
		while(tmp<=mid) cnt+=mid/tmp,tmp*=i.fi;
		if(cnt<i.se) return 0;
	}
	return 1;
}
signed main(){
	IOS;TIE;
	cin>>k;
	int l=1,r=k,ans;
	for(int i=2;i*i<=k;i++){
		while(k%i==0) mp[i]++,k/=i;
	}
	if(k>1) mp[k]++;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)) r=mid-1,ans=mid;
		else l=mid+1;
	}
	cout<<ans<<endl;
	return 0;
}

E - Critical Hit

最基础的概率 DP。考虑记 fi 表示使怪物血量降低至 i 的期望攻击次数。同时因为给出的 p 不是实际概率,实际概率为 p÷100,每次写逆元比较麻烦,所以事先算好 E=100mod2,这样 ÷100 时只要 ×E 即可。

初始 fn=0,然后倒序枚举。每个值的贡献由扣两点血和扣一点血组成:

  • 扣两点血( i=n-1 时只能照扣一点算):

fi=fi+(fi+1+(i!=n1)+1)×p×E

  • 扣一点血:

fi=fi+(fi+1+1)×(1p×E)

最后输出 f0 即可。

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
#define mod 998244353
using namespace std;
int n,p,f[200005];
int ksm(int x,int b){
	int ans=1;
	while(b){
		if(b&1) ans=ans*x%mod;
		x=x*x%mod;
		b>>=1;
	}
	return ans;
}
signed main(){
	IOS;TIE;
	cin>>n>>p;
	int E=ksm(100,mod-2);
	f[n]=0;
	for(int i=n-1;i>=0;i--){
		f[i]+=(f[i+1+(i!=n-1)]+1)*p%mod*E%mod,f[i]%=mod;
		f[i]+=(f[i+1]+1)*(1-p*E%mod)%mod,f[i]%=mod;
		f[i]+=mod,f[i]%=mod;
	}
	cout<<f[0]<<endl;
	return 0;
}

F - Pay or Receive

智慧题。赛时贺了个带权并查集,后来发现直接 DFS 似乎更简单?

大题思路差不多。

首先是 nan 的情况,只需判断两点是否在同一连通块中即可。

然后是 inf 的情况。不难发现路径要无限长只能是出现了 >0 的环,这样的话环所在的整个连通块中,任意两点之间都是 inf。考虑如何判断这样的正环。首先按题意建图,然后在每个连通块内跑一遍 DFS 搞出一颗生成树并记下到每个点的距离。若没有正环,则初始连边的距离是和生成树跑出来的距离相等的。换句话说,两点间怎么走距离都是相等的。然后只要给出现距离矛盾的点所在的连通块都打上标记即可。

剩下的直接用生成树跑出来的距离算。

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
#define mod 998244353
using namespace std;
int n,m,q,u,v,w,col[100005],cnt,f[100005];
bool mark[100005],vis[100005];
struct node{
	int to,dis;
};
vector<node> a[100005];
void dfs(int x,int c){
	col[x]=c,vis[x]=1;
	for(int i=0;i<a[x].size();i++){
		node tmp=a[x][i];
		if(!vis[tmp.to]){
			f[tmp.to]=f[x]+tmp.dis;
			dfs(tmp.to,c);
		}
	}
}
signed main(){
	IOS;TIE;
	cin>>n>>m>>q;
	for(int i=1;i<=m;i++){
		cin>>u>>v>>w;
		a[u].push_back({v,w}),a[v].push_back({u,-w});
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]) dfs(i,++cnt);
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<a[i].size();j++){
			node tmp=a[i][j];
			if(f[tmp.to]!=f[i]+tmp.dis) mark[col[i]]=1;
		}
	}
	while(q--){
		cin>>u>>v;
		if(col[u]!=col[v]) cout<<"nan"<<endl;
		else if(mark[col[u]]) cout<<"inf"<<endl;
		else cout<<f[v]-f[u]<<endl;
	}
	return 0;
}

也附上带权并查集的代码:

//If, one day, I finally manage to make my dreams a reality...
//I wonder, will you still be there by my side?
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define int long long
#define y1 cyy
#define fi first
#define se second
#define cnt1(x) __builtin_popcount(x)
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lbt(x) (x&(-x))
#define mod 998244353
using namespace std;
int n,m,q,u,v,w,fa[200005],f[200005];
bool mark[200005];
int find(int x){
	if(x==fa[x]) return x;
	int tmp=fa[x];
	fa[x]=find(fa[x]);
	f[x]+=f[tmp];
	return fa[x];
}
void merge(int x,int y,int fx,int fy,int k){
	fa[fx]=fy;
	f[fx]=f[y]+k-f[x];
	mark[fy]|=mark[fx];
}
signed main(){
	IOS;TIE;
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++){
		cin>>u>>v>>w;
		int fx=find(u),fy=find(v);
		if(fx^fy) merge(u,v,fx,fy,w);
		else if(f[u]^(f[v]+w)) mark[fx]=1;
	}
	while(q--){
		cin>>u>>v;
		int fx=find(u),fy=find(v);
		if(fx^fy) cout<<"nan"<<endl;
		else if(mark[fx]) cout<<"inf"<<endl;
		else cout<<f[u]-f[v]<<endl;
	}
	return 0;
}
posted @   Binary_Lee  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
Title
点击右上角即可分享
微信分享提示