2020牛客暑期多校训练营(第四场)FBH补题报告

F:已知AB两点在一条直线上,CD两点在同一条直线上,已知两条直线平行,已知AC,AD,BC,BD距离,求从AB方向看为CD还是DC

分情况讨论的方法

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	{
		int ac,ad,bc,bd;
		cin >> ac >> ad >> bc >> bd;
		int ans = 0;
		if(ac > ad)
		{
			if(bd >= bc)
			{
				ans = 0;
			}
			else
			{
				if(ad > bd)
				{
					ans = 0;
				}
				else
				ans = 1;
			}
		}
		else
		{
			if(bd <= bc)
				ans = 1;
			else
			{
				if(ac > bc)
				{
					ans = 1;
				}
				else
				{
					ans = 0;
				}
			}
		}
		if(ans)
		{
			cout << "AB//CD" << endl;
		}
		else
		{
			cout << "AB//DC" << endl;
		} 
	}
	return 0;
}

大佬们的思路:
ABCD构成一个梯形,梯形具有对角线之和大于两腰之和的特点;
又或者 设AD与BC交点为O,形成OAC,OBD两个三角形,三角形两边之和大于第三边。
所以,只需要判断AD + BC是否大于AC + BD即可。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	{
		int ac,ad,bc,bd;
		cin >> ac >> ad >> bc >> bd;
		if(ad + bc > ac + bd)
		{
			cout << "AB//CD" << endl;
		}
		else cout << "AB//DC"  << endl;
	}
	return 0;
}

B:给你n与c,求出算式的最大值

算式每一次递归,都会乘一次c,
每一次递归的选择都是选择最大的,而值的增大来源于多个c的相乘。
所以,我们只需要让递归的层次最多即可。
所以,对于n,分解质因数,所有质因数的幂次求和就是递归次数 num。
最终结果就是c的num次方。

每一次在牛客的调试机上写筛或者唯一分解都会出段错误,真是醉了

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 50;
const long long mod = 1e9 + 7;
int zhi[maxn/2] = {0};
int vis[maxn] = {0};
int z = 0; 
void oulashai()
{
	for(int i = 2; i < maxn - 5; i++)
	{
		if(!vis[i])
		{
			zhi[z] = i;
			z++;
		}
		for(int j = 0; j < z && zhi[j]*i < maxn - 5; j++)		
		{
			vis[i*zhi[j]] = 1;
			if(i % zhi[j] == 0)break;
		}
	}
}
long long hanshu(long long a)
{
		long long ans = 0;
        int t = 0;
        while(t < z)
        {
            long long temp = zhi[t] * zhi[t];
            if(temp > a) break;
            while(a % zhi[t] == 0)
            {
                a /= zhi[t];
                ans++;
            }
            t++;
        }
        if(a > 1) ans++;
        return ans;
}
int quickPower(int x, int y)//快速幂加取模
{
    long long result = 1; // 定义答案
    while (y > 0) // 当指数大于 0 时进行幂运算
    {
        if (y & 1) // y 和 1 做与运算,相当于对 2 求模
        {
            result = (result * x) % mod;// 如果 y 为奇数,则结果只乘一个 x
        }
        x = x * x % mod;  // x 乘二次方,下次使用
        y = y >> 1; // y 右移一位,相当于除以 2
    }
    return result % mod; // 返回结果
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    oulashai();
    int t;
    cin >> t;
    while(t--)
    {
    	long long n,c;
    	cin >> n >> c;
    	long long num = hanshu(n);
    	long long ans = quickPower(c,num) % mod;
    	cout << ans << endl;
	}
    return 0;
}

H: 把 1~N 的数进行两两匹配,使得每组对gcd 大于 1。问最多能匹配多少对,并输出匹配。

从大到小遍历质数,遍历n以内所有质数P的倍数,选择其中没有匹配过的,两两匹配。
如果P的倍数为奇数个,就把2倍的留下(待到枚举质数为2的时候再使用)
如果为偶数个,那么两两匹配即可。

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 50;
int zhi[maxn/2] = {0};
int vis[maxn] = {0};
int z = 0;
void oulashai()
{
	vis[0] = 1;
	vis[1] = 1;
	for(long long i = 2; i < maxn; i++)
	{
		if(!vis[i])
		{
			zhi[++z] = i;
		}
		for(long long j = 1; j <= z && zhi[j] * i < maxn; j++)		
		{
			vis[i*zhi[j]] = 1;
			if(i % zhi[j] == 0)break;
		}
	}
}
int flag[maxn];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	oulashai();
	int t;
	cin >> t;
	while(t--)
	{
		int n;
		cin >> n;
		
		for(int i = 1; i <= n; i++)
		{
			flag[i] = 0;
		}//匹配标记 
		vector<int> a,b;
		int ans = 0; 
		int pos = upper_bound(zhi + 1, zhi + 1 + z, n / 2 + 1) - zhi - 1;
		// n/2 以内的最大质因数zhi[pos]
		for(int i = pos; i >= 1; i--)
		{//从大到小枚举所有可能的质因数
			vector<int> v; 
			int t = zhi[i];
			for(int j = t; j <= n; j += t)
			{
				if(!flag[j])
				{
					v.push_back(j);
				}
			}
			int num = v.size();
			if(num > 1)
			{
				ans += num / 2;
				if(num % 2 == 1)
				{
					vector<int> t;
					for(int j = 0; j < num; j++)
					{
						if(v[j] != 2 * zhi[i])
						{
							//cout << v[j] << endl;
							t.push_back(v[j]);
						}
					}
					for(int j = 0; j < t.size(); j+=2)
					{
						a.push_back(t[j]);
						b.push_back(t[j+1]);
						flag[t[j]] = 1;
						flag[t[j+1]] = 1;
					}
				}
				else
				{
					for(int j = 0; j < num; j+=2)
					{
						a.push_back(v[j]);
						b.push_back(v[j+1]);
						flag[v[j]] = 1;
						flag[v[j+1]] = 1;
					}
				}
			}
		}
		cout << ans << endl;
		for(int i = 0; i < ans; i++)
		{
			cout << a[i] << " " << b[i] << endl;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值