牛客周赛 Round 70

小苯晨跑

思路:直接设置一个变量flag=1,如果有不相等的就是1,然后就是输出YES,否则就是NO

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a[200005];
string s;
signed main()
{
	cin>>t;
	while(t--)
	{
		int flag=1;
		for(int i=1;i<=4;i++)
		cin>>a[i];
		for(int i=2;i<=4;i++)
		{
			if(a[i]!=a[i-1])
			{
				flag=0;
			}
		}
		if(flag==1)
		{
			cout<<"NO\n";
		}
		else
		{
			cout<<"YES\n";
		}
	}
	return 0;
}

小苯过马路

思路:分情况讨论,假如一开始就是红灯,那么变成绿灯后,一定可以通过,所以就是输出k+t

如果是绿灯,如果可以直接通过,即k>=t,那么就是要输出t

否则就是,等完这个,还要再等一个红灯k+x+t

#include<bits/stdc++.h>
using namespace std;
#define int long long
int x,y,k,t;
char c;
signed main()
{
	cin>>x>>y>>k>>t;
	cin>>c;
	if(c=='R')
	{
		cout<<k+t<<"\n";
	}
	else
	{
		if(k<t)
		{
			cout<<k+x+t<<"\n";
		}
		else
		{
			cout<<t<<"\n";
		}
	}
	return 0;
}

 小苯的字符串染色

思路:因为不需要找到最小的操作次数,所以只要碰到是黑的就记录就可以了,先输出有多少个黑色方块数,然后再输出,每个位置就好了

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a[200005];
string s;
void solve()
{
	cin>>n;
	cin>>s;
	s=' '+s;
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='1')
		{
			cnt++;
		}
	}
	cout<<cnt<<"\n";
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='1')
		{
			cout<<i<<" "<<i<<"\n";
		}
	}
}

signed main()
{
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

小苯的能量项链

思路:通过题意可以发现,我们只能发现最终只能保留两只珠子,因此,当n的个数小于3的时候,就直接输出累计和即可,否则,要统计后缀和,就是去处理a[i],当前面只删除了i-1个数的时候,那么后面去统计的就是maxn[max(i+1,n-(k-i+1))],maxn数组用于统计后缀最大值,因为k可能会大于n,所以导致数组超界,所以要取一个最值

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a[500005];
string s;
int sum=0;
int maxn[500005];
//只能保证剩下两颗珠子
void solve()
{
	sum=0;
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum+=a[i];
	}
	if(n<3)
	{
		cout<<sum<<'\n';
		return ;
	}
	for(int i=n;i>=1;i--)
	{
		maxn[i]=max(maxn[i+1],a[i]);
	}
	//前缀最大值就是n-1,但是你最多只能遍历到k个
	int ans=0;
	for(int i=1;i<=min(n-1,k+1);i++)
	{
		ans=max(ans,a[i]+maxn[max(i+1,n-(k-i+1))]);
	} 
	cout<<ans<<'\n';
}
signed main()
{
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

小苯的最短路

思路:我们很明显发现每个点的最短路权值就是1^i,因此我们s可以发现是有规律的,从2开始,每四个可以视为一组,当减去1之后,

取模为1,则输出n+1

取模为2,输出1

取模为3,输出n,

取模为4,输出0

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
void solve()
{
    cin>>n;
    if(n==1)
    {
        cout<<0<<"\n";
    }
    else 
    {
        int flag=n;
        n-=1;
        if(n%4==0)
        {
            cout<<0<<"\n";
        }
        else if(n%4==2)
        {
            cout<<1<<"\n";
        }
        else if(n%4==1)
        {
            cout<<flag+1<<"\n";
        }
        else
        {
            cout<<flag<<"\n";
        }

    }
}
signed main()
{
    cin>>t;
    while(t--)
        solve();
    return 0;
}

 小苯的优雅好序列

这题做的时间还是比较长的,因为确实难,但是有一个困惑的地方就是为什么不能排序,排序就错了一个点

算了,等待大佬来给我讲解吧,先说我自己推出来的思路

因为我们要确保ai和aj能有整除的关系,大的能够整除所有小的,因此我们可以将ai设置为x,aj设置为y,假如说我们要增加一个因子为c,因此我们可以得到方程式

(y+c)/(x+c)=Z(Z是整数)

化简式子的到(y-x)/(x+c)=(Z-1),因此x和y的差d是(x+c)的倍数 ,因此我们可以考虑遍历最大值和最小值的差的因数,当因数c满足c-minn<=k&&c-minn>0的时候,就可以得到一种结果,但是遍历一遍整个数太大了,因此我们可以只考虑遍历sqrt(c),另一半的因子就是c/i,然后去判断能否让整个数列变成题目要求的,即可,时间复杂度为O(N)

整体时间复杂度为O(NlogN)

#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n, k;
int a[200005];
int minn;
int maxn;
bool check(int x) 
{
    if (x - minn > k || x - minn <= 0) 
    {
    	return false;
	}
	int b[n+1];
    for(int i=1;i<=n;i++)
    b[i]=a[i];
    for(int i=1;i<=n;i++)
    {  
        b[i] += x - minn;  
    }  
    for (int i = 2; i <= n; i++) 
    {  
         if (max(b[i],b[i-1]) % min(b[i],b[i - 1]) != 0) 
        return false;  
    }  

    return true;
}

void solve() 
{
    cin >> n >> k;
    minn=0x3f3f3f3f;
    maxn=0;
    for (int i = 1; i <= n; i++) 
	{
        cin >> a[i];
        minn=min(minn,a[i]);
        maxn=max(maxn,a[i]);
    }
    if (maxn-minn==0) {
        cout << k << " " << (k * (k + 1)) / 2 << "\n";
        return;
    }
    int d = maxn-minn;  
    int cnt = 0, sum = 0;

    for (int i = 1; i * i <= d; i++) {
        if (d % i == 0) {
            if (check(i)) {
                cnt++;
                sum += i - minn;
            }
            if (i != d / i && check(d / i)) {
                cnt++;
                sum += (d / i) - minn;
            }
        }
    }
    cout << cnt << " " << sum << "\n";
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值