#725 (Div. 3) D(线性筛+思维 F 思维 G (思维+二分

这篇博客探讨了线性筛法在解决数论问题中的应用,如找到两个数通过质因子分解达到相等所需的最少操作次数。同时,还介绍了如何计算数字变化的次数,以及在给定限制下最大化糖果打包的方法。这些问题涉及数学思维和组合优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D. Another Problem About Dividing Numbers
线性筛+思维
他让我们恰好通过 k 次操作来让两个数相等,我们可以取极限次数,就是除一遍这个数所有的质因子,直至为1。也就是统计两个数,所有质因子的个数的加和,这是我们能操作的最多次数。如果 k 超过这个数目,那么一定不行,否则我们可以通过组合质因子,来构造出恰好 k 次操作来让两个数相等

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e5 + 9;
ll t = 1, n, m, k, l, r;
ll p[N], cnt,v[N];
void xxs()
{
	for(ll i = 2; i <= N - 9; ++i)
	{
		if(!v[i]) p[cnt++] = i;
		for(int j = 0; j < cnt && p[j]*i < N - 9; ++j)
		{
			v[p[j]*i] = 1;
			if(i % p[j] == 0) break;
		}
	}
}
void solve()
{
	cin >> l >> r >> k;
	if(k == 1)
	{
		if(l != r && (l % r == 0 || r % l == 0)) cout << "YES\n";
		else cout << "NO\n";
	}
	else 
	{
		int ans = 0;
		for(int i = 0; i < cnt; ++i)
		{
			while(l % p[i] == 0) l/= p[i], ++ans;
			while(r % p[i] == 0) r/= p[i], ++ans;
		}
		if(l > 1) ++ans; if(r > 1) ++ans;
// 统计两个数的质因子的个数
//只要总数大于等于 k,都可以进行某种组合满足恰好 k 次操作 
		if(k > ans) cout << "NO\n";
		else cout << "YES\n";
	}
}
int main()
{
	xxs();
	cin >> t;
	while(t--)
		solve();
	return 0;
}

F. Interesting Function
假设 l =10, r = 200
首先明确个位数变了多少次, 仔细想想其实就是 200-10次 200-10=190
然后是十位变了多少次, 那不就转化成 1 - 20 变化了多少次吗,20-1=19
然后就结束了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 9;
ll t = 1, n, m, k, l, r;
void solve()
{
	cin >> l >> r;
	int ans = 0, base = 1;
	for(int i = 0; i <= 9; ++i)
	{
		ans += r / base - l / base;
		base *= 10;
	}
	cout << ans << endl;
}
int main()
{
	cin >> t;
	while(t--)
		solve();
	return 0;
}

G. Gift Set
大佬题解
题意:
给定 x , y , a , b x,y,a,b x,y,a,b 四个整数,表示有 x x x 个红色糖果和 y y y 个蓝色糖果。现在有两种打包方式:

  1. a a a 个红色糖果 和 b b b 个蓝色糖果
  2. b b b 个红色糖果 和 a a a 个蓝色糖果

求最多打包个数
思路:
t 1 t_1 t1 个 第一种打包方式, t 2 t_2 t2 个第二种打包方式,在满足下列不等式的情况下,使得 t 1 + t 2 t_1+t_2 t1+t2 最大

  1. t 1 ∗ a + t 2 ∗ b < = x t_1*a+t_2*b <= x t1a+t2b<=x
  2. t 1 ∗ b + t 2 ∗ a < = y t_1*b+t_2*a<=y t1b+t2a<=y

最大化 t 1 + t 2 t_1+t_2 t1+t2,显然我们去二分,设 k k k 种方式一
那么不等式变成了

  1. k ∗ a + ( m i d − k ) ∗ b < = x k*a+(mid-k)*b<=x ka+(midk)b<=x
  2. k ∗ b + ( m i d − k ) ∗ a < = y k*b+(mid-k)*a<=y kb+(midk)a<=y

显然交换 x , y x,y x,y a , b a,b a,b 不会影响答案,不妨设 x < = y , a < = b x<=y,a<=b x<=y,a<=b 化简一下可以得到
0 < = x − b ∗ m i d a − b < = k < = y − a ∗ m i d b − a < = m i d 0<=\frac{x-b*mid}{a-b}<=k<= \frac{y-a*mid}{b-a} <= mid 0<=abxbmid<=k<=bayamid<=mid
然后 c h e c k check check 不等式是否成立就好了,注意 k k k 的代表的是方式一的数量,范围应该是 [ 0 , m i d ] [0,mid] [0,mid] ,注意特判 a = b a=b a=b
code:

#include<bits/stdc++.h>
#define endl '\n'
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const ll N = 1e3 + 9;
ll l, r, n, m, x, y, t;
ll a, b;
bool check(int mid)
{
	int x1 = ceil(1.0 * (x - b * mid) / (a - b));
	int x2 = floor(1.0 * (y - a * mid) / (b - a));
	x1 = max(x1, 0); x2 = min(x2, mid);
	return x1 <= x2;
}
int main()
{
	cin >> t;
	while(t--)
	{
		scanf("%d %d %d %d", &x, &y, &a, &b);
		if(a == b) cout << min(x, y)/a << endl;
		else
		{
			if(a > b) swap(a, b);
			l = 0, r = inf;
			while(l < r)
			{
				int mid = (l + r) >> 1;
				if(check(mid)) l = mid + 1;
				else r = mid;
			}
			cout << r << endl;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值