牛客小白月赛60

比赛链接:牛客小白月赛60_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

A: 小竹与妈妈

思路:简单数学题

代码:

#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;

inline void solve(){
	int a,b,c;cin>>a>>b>>c;
	cout<<(c-b)/a<<"\n";
}

signed main(){
	fast;
	//int T;cin>>T;
	//while(T--)
	solve();	
}

B:走丢的小竹

思路:统计每个点对应有多少个出口,因为当前坏人所在的位置所对应的出口是不能走的。所以总的方案数是除了坏人所占据的出口的所有出口数的和

代码:

#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
int cnt[N];

inline void solve(){
	int n,m,q,maxx=0;cin>>n>>m>>q;
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		cnt[x]++;maxx=max(maxx,x);
	}
	int res=0;
	for(int i=1;i<=maxx;i++) res+=cnt[i];
	while(q--){
		int x;cin>>x;
		int ans=res-cnt[x];
		cout<<ans<<"\n";
	}
}

signed main(){
	fast;
	//int T;cin>>T;
	//while(T--)
	solve();	
}

C:小竹关禁闭

思路:DP。我们考虑,DP【i】为取到第i个绳长所得到的最长长度。

代码:

#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
int a[N],dp[N];

inline void solve(){
	int n,k;cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i],dp[i]=a[i];
	for(int i=1;i<=n;i++){
		for(int j=i+k+1;j<=n;j++){
			dp[j]=max(dp[j],dp[i]+a[j]);
		}
	}
	int res=0;
	for(int i=1;i<=n;i++) res=max(res,dp[i]);
	cout<<res<<"\n";
	
}

signed main(){
	fast;
	//int T;cin>>T;
	//while(T--)
	solve();	
}

D:游戏购买!

方法:BFS。首先BFS预处理求出起点和中间(小胖和小猪家)分别到每个商店的最短距离,然后枚举所有符合条件的商店位置,每个商店到两家的距离之和就是距离,所有这样的距离求和即可

代码: 

#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e3+10;
typedef pair<int,int> PII;
int a[N][N],dist1[N][N],dist2[N][N];
bool vis[N][N],pd[N][N];//pd:标记合法点位
int n,m,w,sx,sy,ex,ey;
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

inline void solve(){
	cin>>n>>m>>w>>sx>>sy>>ex>>ey;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	queue<PII>q,qq;
	dist1[sx][sy]=0;vis[sx][sy]=true;
	q.push({sx,sy});
	while(!q.empty()){
		int x=q.front().first,y=q.front().second;
		q.pop();
		for(int i=0;i<4;i++){
			int xx=x+d[i][0],yy=y+d[i][1];
			if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||a[xx][yy]==-1) continue;
			dist1[xx][yy]=dist1[x][y]+1;vis[xx][yy]=true;
			q.push({xx,yy});
			if(a[xx][yy]>w) pd[xx][yy]=true;	
		}
	}
	memset(vis,false,sizeof vis);
	int ans=1e9+10;
	dist2[ex][ey]=0;vis[ex][ey]=true;
	q.push({ex,ey});
	while(!q.empty()){
		int x=q.front().first,y=q.front().second;
		q.pop();
		for(int i=0;i<4;i++){
			int xx=x+d[i][0],yy=y+d[i][1];
			if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||a[xx][yy]==-1) continue;
			dist2[xx][yy]=dist2[x][y]+1;vis[xx][yy]=true;
			q.push({xx,yy});
			//合法点位到两目标点位的距离和
            if(pd[xx][yy]) ans=min(ans,dist1[xx][yy]+dist2[xx][yy]);
			q.push({xx,yy});	
		}	
	}
	if(ans>1e8) cout<<"-1";
	else cout<<ans;
}

signed main(){
	fast;
	//int T;cin>>T;
	//while(T--)
	solve();	
}

E:寻找小竹!

分析:并查集+质数筛。读完题发现,我们需要建立一棵树。建树的规则:建立边的时候,需要判断一下边两头的节点是否互为优雅(最大公约数是否有至少两个不同的质因数)。利用并查集来进行合并节点,利用一个数组来维护连通块的大小。

并查集:并查集(基础)_Black_Chocolate.的博客-CSDN博客

代码:

#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e7;
int a[N],fa[N],sz[N],cnt[N];
//fa:代表i号节点的代表元    sz:维护联通块的大小 cnt:记录数字i的质因数个数
int find(int x){//查找节点的代表元
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}

void solve(){
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];fa[i]=i;sz[i]=1;
    }
    for(int i=2;i<=n;i++){//质因子数筛
        if(cnt[i]) continue;
        for(int j=i;j<=1e7;j+=i){
            cnt[j]++;
        }
    }
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        int g=__gcd(a[x],a[y]);
        if(cnt[g]>=2){//满足条件就合并节点
            sz[find(y)]+=sz[find(x)];//维护大小
            fa[find(x)]=find(y);//合并节点
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans=max(ans,sz[find(i)]);//找最大值
    }
    cout<<ans<<'\n';
}

signed main(){
	fast;
	//int T;cin>>T;
	//while(T--)
	solve();	
}

F:被抓住的小竹

ps:这是一道关于数论的题,目前还没有能力去解决,这里先附上一篇代码,自行理解一下吧。(以后待补题解)

代码:

#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e7;
const int mod=1e9+7;
int a[N];

int power(int a,int b){//快速幂
	int res=1;
	while(b){
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}

int inv(int x){
	return power(x,mod-2);
}

void solve(){
	a[0]=1;
	for(int i=1;i<=1e5+10;i++) a[i]=a[i-1]*i%mod;
	int k;cin>>k;
	while(k--){
		int x;cin>>x;
		cout<<(x*x%mod)*(x-1)%mod*a[x+3]%mod*inv(96)%mod<<"\n";//不理解qaq..0.0.
	}
}

signed main(){
	fast;
	//int T;cin>>T;
	//while(T--)
	solve();	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值