牛客小白月赛60题解

94 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

A

A

题意:

已知小明妈妈的年龄求小明的年龄

题解:

推公式呀:妈妈为x,设小明为y

可以得到

y = a*x+b

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
    
void solve()
{
    ll a,b,c;
    cin >> a >> b >> c;
    cout << (c - b) / a << '\n';
}
int main()
{
    int t = 1;
    //scanf("%d",&t);
    while(t--)
    {
        solve();
    }
}

B

题意:

m个房间,n个出口,不能走到罪犯的房间,所以相减一下就好了

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 500000 + 10;
ll a[100010];
void solve()
{
	ll n,m,q;
    cin >> n >> m >> q;
    for(int i = 1;i <= n;i ++)
    {
        int x;
        cin >> x;
        a[x]++;
    }
    while(q--)
    {
        ll x;
        cin >> x;
        cout << n - a[x] << '\n';
    }
}
int main()
{
    int t = 1;
    //scanf("%d",&t);
    while(t--)
    {
        solve();
    }
}

C

2000,找最大,直接dp(dp学的好烂,还好这个不难呜呜呜)

f存距离。就是找到i前面满足条件的最大距离+本身

状态转移方程:f[i] = max(f[i],f[j]+a[i]);

对了要注意一下并不是最后一个f[n]最大,不要忘记他还有一个条件相隔距离大于k

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 20010;
ll a[N], f[N];
int main()
{
    int t = 1;
	while(t--)
    {
         ll n, k;
        scanf("%lld %lld",&n,&k);
        for (int i = 1; i <= n; i ++) 
            scanf("%lld",&a[i]);
        ll ans = 0;
        for (int i = 1; i <= n; i ++)
        {
            f[i] = max(f[i], a[i]);
            for(int j = 1;j + k < i;j ++)
            {
                f[i] = max(f[j]+ a[i],f[i]);
            }
            ans = max(f[i],ans);
        }
        printf("%lld\n",ans);
	}
}

D

最小距离,好bfs,可是我是sb他一直报内存超限,我找不到错哪了,最后才发现这个不能开long long(呜呜呜,痛,太痛了)

大家应该都会bfs,注意是状态,他要求必须带超过x的刺激度,所以他可能会重复走一些格子,这个时候我们可以开三维,前两维表示坐标,最后一位表示状态。因为他的刺激度是交换,不是相加,所以我们可以在输入的时候判断一下,如果他大于0并且小于等于x那么全为0,那么剩下来的就是-1,走不了,0,已经>0要去的地方,这样我们可以吧状态压到2种,一种0,需要去找商店,一种1,已经去了商店去目的地就可以了

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 2011;
int n,m,h;
int f[N][N][2];
int s[N][N];
int x,y,xx,yy;
struct now{
	int xxx;
	int yyy;
	int num;
	int cnt;
};
queue<now>q;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void bfs()
{
	q.push({x,y,0,0});
	f[x][y][0] = 1;
	while(q.size())
	{
		//printf("-1\n");
		auto [a,b,c,d] = q.front();
		q.pop();
		for(int i = 0;i < 4;i ++)
		{
			int a1 = a+dx[i];
            int b1 = b+dy[i];
            int z = s[a1][b1];
            int rx = max(s[a1][b1],c);
            int w = 0;
            if(rx > 0)
                w = 1;
            if(z < 0)
                continue;
            if(a1 < 1 || a1 > n || b1 < 1 || b1 > m)
                continue;
            if(f[a1][b1][w])
                continue;
             //cout << a1 <<' ' << b1 << ' '<< rx << ' ' << w << '\n';
            if(a1 == xx && b1 == yy && rx > h )
            {
                printf("%d\n",d+1);
                return ;
            }
            q.push({a1,b1,rx,d+1});
            f[a1][b1][w] = 1;
		}
	}
	printf("-1\n");
    return ;
}
int main()
{
	scanf("%d %d %d",&n,&m,&h);
    scanf("%d %d %d %d",&x,&y,&xx,&yy);
	for(int i = 1;i <= n;i ++)
	   for(int j = 1;j <= m;j ++)
       {
            scanf("%d",&s[i][j]);
            if(s[i][j] <= h && s[i][j] > 0)
                s[i][j] = 0;
       }
	bfs();
}

E

一看并查集吧,还好不是带权并查集(呜呜呜,这个搞不懂),但是判断素数需要欧拉筛搞一下,然后有木有发现两个都含那么直接求他们的gcd,再判断一下从1~gcd(x,y)之间有多少的质数可以整除gcd(x,y)

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 5e6 + 10;
ll a[N],c[N],d[N];
ll n;
int prime[N];
bool vis[N];
int cnt=0;
ll pos[N];
int find(int ans)
{
    if(d[ans]!=ans)
    d[ans] = find(d[ans]);
    return d[ans];
}
void solve()
{
	scanf("%lld",&n);
    for(int i = 1;i <= n;i ++)
    {
        scanf("%lld",&a[i]);
        d[i] = i;
    }
    int x,y;
    for(int i = 1;i < n;i ++)
    {
        cin >> x >> y;
        ll res = __gcd(a[x],a[y]);
        //res = 3;
        if(!c[res])
        {
            ll cnt1 = 0;
           for(int j = 0;prime[j]<= res;j ++)
           {
               if(res % prime[j] == 0)
               {
                   cnt1 ++;
               }
               if(cnt1 >= 2)
               {
                   d[find(x)]=find(y);
                   //cout << x << " " << y << '\n';
                   break;
               }
           }
        }
    }
    ll ans = 0;
    for(int i = 1;i <= n;i ++)
    {
        ans = max(ans,++pos[find(i)]);
    }
    cout << ans << '\n';
}
int main()
{
	int t = 1;
	//scanf("%d",&t);
    for(int i=2;i<=5e6;++i)
	{
		if(!vis[i])
		{prime[cnt++]=i;vis[i]=true;}//vis[i]置为true或不置true都可以
		for(int j=0;j<cnt;++j)
		{
			if(i*prime[j]>5e6)//判断是否越界
				break;
			vis[i*prime[j]]=true;//筛数
			if(i%prime[j]==0)//时间复杂度为O(n)的关键!
				break;
		}
	}
    prime[0] = 2;
    for(int i = 1;i <= cnt;i ++)//这个不能少,不然会超时,就是把所有的质数存起来放到后面判断
    {
        c[prime[i]] = 1;
    }
	while(t--)
	{
		solve();
	}
}

F

实力不够,哭死(难受)