牛客小白月赛106

这场比赛没有做好,只拿下了三道题,当时该跳过第四道去处理第五道题的,第四道题的思路当时想错了,以为是要用数论去求解,其实普通的最短路就可以求出,当时没有想好,以为是自己没做对

最后DISCO

思路:我们首先分情况看b是否是0

1.当b是0的时候, a^b次方永远是1,所以,结果就是c+d是否是奇数,若一个是奇数,一个是偶数,就输出YES,否则输出NO

2.当b不是0的时候,那么奇数的次方永远是奇数,偶数的次方永远是偶数,所以只需要看acd的就行即可

ac都为奇数才是奇数,d为偶数则是YES,当d为奇数那么就是NO

ac一个奇数,一个偶数,或者两个偶数,当d为奇数才是YES,否则就是NO

然后就可以轻易ac了

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a,b,c,d;

signed main()
{
	cin>>a>>b>>c>>d;
	if(b==0)
	{
		if((c+d)%2==1)
		{
			cout<<"YES\n";
			return 0;
		}
		else
		{
			cout<<"NO\n";
			return 0;
		}
	}
	int flag1=a%2;
	int flag2=c%2;
	int flag3=d%2;
	if((flag1==1&&flag2==1&&flag3==0)||(flag1==0&&flag2==1&&flag3==1)||(flag1==1&&flag2==0&&flag3==1)||(flag1==0&&flag2==0&&flag3==1))
	{
		cout<<"YES\n";
	}
	else
	{
		cout<<"NO\n";
	}
	return 0;
}

末日DISCO

很水的一个构造题吧,自己手玩一下就发现一个规律,只要二维数组按照对角线是对称的就是满足题意的一种组合

比如说3大小的二维矩阵

1 2 3

2 4 5

3  5 6

只要按照对角线对称即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a[505][505];

signed main()
{
	cin>>n;
	int num=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n;j++)
		{
			a[i][j]=num;
			num++;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]==0)
			{
				a[i][j]=a[j][i];
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cout<<a[i][j]<<" ";
		}
		cout<<"\n";
	}
	return 0;
}

明日DISCO

思路:我们发现,这个题目的要求是让你把所有格子都变成0,那么我们从题目上可知,只有一个数比别的数都大,或者一个数别四周的数都小,才能进行加减

那么我们手玩一下发现,加入一个整数旁边也有正数,那么一定会减到与四周最大的正数相等的时候,那时候就无法操作了,所以我们正数的四周只能是负数或0,负数的四周只能是正数或0

找到结论直接写

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a[505][505];

signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
		}
	}
	int flag=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]>0&&a[i][j+1]>0)
			{
				flag=0;
			}
			if(a[i][j]<0&&a[i][j+1]<0)
			{
				flag=0;
			}
		}
	}
	for(int j=1;j<=n;j++)
	{
		for(int i=1;i<=n;i++)
		{
			if(a[i][j]>0&&a[i+1][j]>0)
			{
				flag=0;
			}
			if(a[i][j]<0&&a[i+1][j]<0)
			{
				flag=0;
			}
		}
	}
	if(flag==1)
	{
		cout<<"YES\n";
	}
	else
	{
		cout<<"NO\n";
	}
	return 0;
}

 太阳系DISCO

思路:我们完全可以将其转变成一个最短路的问题,用bfs去搜索,只不过将逆时针的变成顺时针走n-y

那么我们就可以去不断将没有查找过的点加入队列

然后更新当前点的最短距离

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int INF = LLONG_MAX;
int n, k, a, b, x, y;
int step[200005];  
int vis[200005];   
queue<pair<int, int>> que; 
void bfs(int start) 
{
    que.push({start, 0});
    step[start] = 0;
    while (!que.empty()) 
	{
        auto [v, cnt] = que.front();
        que.pop();
        
        if (cnt < k) 
		{
            if (step[(v + n / 2) % n] > step[v] + 1) 
			{
                step[(v + n / 2) % n] = step[v] + 1;
                que.push({(v + n / 2) % n, cnt + 1});
            }
        }
        if (step[(v + x) % n]>step[v] + 1) 
		{
            step[(v + x) % n]=step[v] + 1;
            que.push({(v + x) % n, cnt});
        }

        if (step[(v + n - y) % n] > step[v] + 1) 
		{
            step[(v + n - y) % n] = step[v] + 1;
            que.push({(v + n - y) % n, cnt});
        }
    }
}

signed main() 
{
    cin >> n >> k >> a >> b >> x >> y;
    fill(step, step + n, INF);
    step[a] = 0;
    bfs(a);
    if (step[b] == INF) 
	{
        cout << -1 << endl;
    } 
	else 
	{
        cout << step[b] << endl;
    }
    return 0;
}

 普通DISCO-1

思路:我们发现就是去找到树内最长的那个链和除了主链以外的最长的链的和减1就是最终结果

跑两边dfs就可以解决问题了

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

int n;
int u,v;
vector<int> e[500005];
int dep[500005];
int prison[500005];
int ans=0;
void dfs1(int v,int fa)
{
	dep[v]=1;
	for(int u:e[v])
	{
		if(u!=fa)
		{
			dfs1(u,v);
			dep[v]=max(dep[v],dep[u]+1);
			if(dep[u]>dep[prison[v]])
			{
				prison[v]=u;
			}
		}
	}
}
void dfs2(int v,int fa)
{
	for(int u:e[v])
	{
		if(u!=fa&&u!=prison[v])
		{
			ans=max(ans,dep[u]);
		}
	}
	if(prison[v]!=0)
	{
		dfs2(prison[v],v);
	}
}
signed main()
{
	cin>>n;
	for(int i=1;i<=n-1;i++)
	{
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs1(1,-1);
	dfs2(1,-1);
	cout<<dep[1]+max(ans-1,0)<<"\n";
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值