8.11个人训练总结

本文探讨了多种算法问题的解决方案,包括洛谷P2678中的最短距离问题,Codeforces1541A的全排列操作,1542B的集合元素条件,1542C的数论问题,1543A的最大公约数,以及1557A和1557B的序列操作。通过分析和代码展示,展示了如何利用二分查找、数学逻辑和贪心策略解决这些挑战。
摘要由CSDN通过智能技术生成

洛谷 P2678 题目链接:点击这里传送

在这里插入图片描述
思路:
对最短距离的最大值进行二分答案,具体看代码注释

#include<bits/stdc++.h>
using namespace std;
long long maxl, n, m, ans;//距离,岩石数,至多移走的岩石数
long long a[500005];//记录n块岩石与起点的距离
bool flag(long long dis)
{
	long long step = 0;
	long long f = 0;
	for (long long i = 1; i <= n + 1; i++)
	{
		if (dis > (a[i] - a[f]))//假设最短距离为dis,出现了比dis还短的距离,那把这块石头移走
		{
			step++;
			f = f;
		}
		else { f = i; }
	}

	return m >= step;
}
int main()
{
	cin >> maxl >> n >> m;
	for (long long i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	a[n + 1] = maxl;
	long long l = 1, r = maxl;//对最短距离的最大值进行二分答案
	while (l <= r)
	{
		long long mid = (l + r) / 2;
		if (flag(mid))//还可以继续增大最短距离
		{
			ans = mid;
			l = mid + 1;
		}
		else { r = mid - 1; }
	}
	cout << ans;
	return 0;
}

Codeforces 1541A 题目链接:点击这里传送

在这里插入图片描述
题意:
给出一个全排列,你可以让某一个元素左移或右移。最少要几次这样的操作能使所有的元素都不在他们的初始位置上。
思路:
偶数两两交换,奇数n-3再两两交换。

#include<bits/stdc++.h>
using namespace std;
int n, t;

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--)
	{
		cin >> n;
		if (n % 2 == 0)
		{
			for (int i = 1; i <= n / 2; i++)
			{
				cout << 2 * i  << " " << 2 * i-1 <<" ";
			}
			cout << endl;
		}
		else
		{
			cout << "3 1 2 ";
			if (n == 3) continue;
			for (int i = 1; i <= (n - 3) / 2; i++)
			{
				cout << 2 * (i + 1) + 1 << " " << 2 * (i + 1)<<" ";
			}
			cout << endl;
		}
	}

	return 0;
}

Codeforces 1542B 题目链接:点击这里传送

在这里插入图片描述
题意:
1存在于这个集合。
这个集合的元素 × \times ×a存在于这个集合,这个集合的元素+b存在于这个元素。
现给出n,问n是否存在于这个元素。
思路:
存在于集合中的元素都满足这样的条件:由两部分的和组成,第一部分是 a k a^k ak,第二部分能被b整除。

#include<bits/stdc++.h>
using namespace std;
long long t,n,a,b;

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n>>a>>b;
        int f=0;
        if(a==1)
        {
            if(b==1) 
            {
                cout<<"YES"<<endl;
                continue;
            }
            if(n%b==1) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
            continue;
        }
        for(long long i=1;i<=n;i*=a)
        {
            if((n-i)%b==0)
            {
                f=1;
                break;
            }
        }
        if(f==0) cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }

    return 0;
}

Codeforces 1542C 题目链接:点击这里传送

在这里插入图片描述
题意:
f(n)是最小的不是n的因数的数字。求f(1)+f(2)+…+f(n)
思路:
算贡献。n/lcm(1,2,3,…,m-1)是因子不含m的个数,n/lcm(1,2,3,…,m)是因子不含m+1的个数,减一下就是f(x)=m的个数,再乘m就是m的贡献值。把1~n都这样算一下累加起来就是答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX_TEMP 44
#define mod 1000000007
ll gcd(ll a,ll b)
{
    if(a<b) swap(a,b);
    while(b)
    {
        ll temp=a%b;
        a=b;
        b=temp;
    }
    return a;
}
ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}
ll t,n,ans;
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n;
        ll temp1=1;//大的
        ll temp2=1;//小的
        ll ans=0;
        for(ll i=2;i<=MAX_TEMP;i++)// i*(n/lcm(1,2...i-1)-n/(lcm(1,2...i)))
        {
            temp1=lcm(temp1,i-1);
            temp2=lcm(temp2,i);
            if(n/temp1==0) break;
            ans=ans+i*(n/temp1-n/temp2);
        }
        cout<<ans%mod<<endl;
    }

    return 0;
}

Codeforces 1543A 题目链接:点击这里传送

在这里插入图片描述
题意:
给出两个数,你可以使他们共同变大或变小。求他们gcd的最大值。
思路:
差值是他们最大的gcd。变大变小算一下比较最小值。

#include<bits/stdc++.h>
using namespace std;
long long t,a,b;
#define ll long long
ll solve(ll x,ll y)
{
    for(int i=1;;i++)
    {
        ll temp=y*i;
        if(temp>=x) return temp;
    }
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>a>>b;
        if(a==b)
        {
            cout<<"0 0"<<endl;
            continue;
        }
        ll mini=min(a,b);
        ll maxi=max(a,b);
        cout<<maxi-mini<<" ";
        ll maxn=solve(mini,maxi-mini);
        cout<<min(maxn-mini,mini%(maxi-mini))<<endl;
    }

    return 0;
}

Codeforces 1542A 题目链接:点击这里传送

在这里插入图片描述
题意:
任意选两个数组成一对,n对下来后每对的和要求为奇数。
思路:
统计奇数和偶数的个数,相同就输出YES,否则输出NO

#include<bits/stdc++.h>
using namespace std;
int t, n;
#define MAXN 200005
int a[MAXN];

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--)
	{
		cin >> n; for (int i = 1; i <= 2*n; i++) cin >> a[i];
		int cnt1 = 0; int cnt2 = 0;
		for (int i = 1; i <= 2 * n; i++)
		{
			if (a[i] % 2) cnt1++;
			else cnt2++;
		}
		if (cnt1 == cnt2) cout << "YES" << endl;
		else cout << "NO" << endl;
	}

	return 0;
}

Codeforces 1557A 题目链接:点击这里传送

在这里插入图片描述
题意:
将一个序列分成两部分,使这两部分的平均数的和最大。
思路:
最大的单独拿出来。试想,如果拿两个最大的,两个部分的平均值都会变小,再拿下去更小,很容易证明这样贪心最优。

#include<bits/stdc++.h>
using namespace std;
double maxn, sum, temp;
int t,n;
int main()
{
	cin >> t;
	while (t--)
	{
		sum = 0;
		maxn = -999999999;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
		{
			scanf("%lf", &temp);
			maxn = max(maxn, temp);
			sum += temp;
		}
		printf("%.6lf\n", (sum - maxn) / (n - 1) + 0.0 + maxn * 1.0);
	}

	return 0;
}

Codeforces 1557B 题目链接:点击这里传送

在这里插入图片描述

题意:
每次将一个序列最多分成k部分,这k个整体可以任意调换位置。问能否整体实现升序。
思路:
排序后标记好各自排序后的位置。再对原数组那些不满足a[i+1].id-1=a[i].id的情况计数。因为这种时候就需要分开来排序。当计数个数大于k是,就不成立。

#include<bits/stdc++.h>
using namespace std;
int t, n,k;
#define MAXN 100005
struct node {
	int id;
	int val;
}a[MAXN];
bool cmp(node a, node b) { return a.val < b.val; }

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--)
	{
		cin >> n>>k;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i].val;
			a[i].id = i;
		}
		sort(a + 1, a + 1 + n, cmp);
		int cnt = 1;
		for (int i = 1; i < n; i++)
		{
			if (a[i + 1].id - a[i].id != 1) cnt++;

		}
		if (cnt > k) cout << "NO" << endl;
		else cout << "YES" << endl;
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值