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 个蓝色糖果。现在有两种打包方式:
- a a a 个红色糖果 和 b b b 个蓝色糖果
- 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 最大
- t 1 ∗ a + t 2 ∗ b < = x t_1*a+t_2*b <= x t1∗a+t2∗b<=x
- t 1 ∗ b + t 2 ∗ a < = y t_1*b+t_2*a<=y t1∗b+t2∗a<=y
最大化
t
1
+
t
2
t_1+t_2
t1+t2,显然我们去二分,设
k
k
k 种方式一
那么不等式变成了
- k ∗ a + ( m i d − k ) ∗ b < = x k*a+(mid-k)*b<=x k∗a+(mid−k)∗b<=x
- k ∗ b + ( m i d − k ) ∗ a < = y k*b+(mid-k)*a<=y k∗b+(mid−k)∗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<=a−bx−b∗mid<=k<=b−ay−a∗mid<=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;
}