文章目录
一、概况
比赛名称:Codeforces Round 725 (Div. 3)
日期: 2024.2.3
晚上在家做了A和B,课上又做了C和F。
所以为什么F题这么简单?
二、正解
D. Another Problem About Dividing Numbers
1 题目描述
给定两个整数 a , b a, b a,b 和一个操作数 k k k。对于每一次操作,你有如下两种选择:
- 选择一个能整除 a a a 的大于一的整数 c c c,用 a c \dfrac{a}{c} ca 替换 a a a。
- 选择一个能整除 b b b 的大于一的整数 c c c,用 b c \dfrac{b}{c} cb 替换 b b b。
然后询问,是否存在一种操作方法,使得在恰好 k k k 次操作后, a = b a=b a=b。
数据范围: 1 < a , b , k < 10 9 1 < a, b, k < {10}^9 1<a,b,k<109。
2 大体思路
-
对于 k = 1 k=1 k=1 的情况:
- 如果
a
a
a 能乘除
b
b
b ,且
a
a
a 不等于
b
b
b ,则可以通过一次操作使得它们相等。因此,输出
YES
- 否则,便无法仅通过一次操作使它们相等,输出
NO
。
- 如果
a
a
a 能乘除
b
b
b ,且
a
a
a 不等于
b
b
b ,则可以通过一次操作使得它们相等。因此,输出
-
对于 k > 1 k>1 k>1 的情况:
- 首先,通过质因数分解函数获取 a a a 和 b b b 的质因数个数,分别记为 k a ka ka 和 k b kb kb 。
- 如果
k
a
+
k
b
<
k
ka+kb<k
ka+kb<k ,则表示质因数个数不足以进行
k
k
k 次操作,因为每次操作至少会使一个质因数被除去,输出
NO
。 - 如果
k
a
+
k
b
≥
k
ka+kb \geq k
ka+kb≥k ,则表示质因数个数足够进行
k
k
k 次操作,因为总共有
k
a
+
k
b
ka+kb
ka+kb 个质因数。输出
YES
。
3 AC代码
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
int fj(int x){//分解质因数
int cnt=0;
for(int i=2;i*i<=x;i++){
while(x%i==0){
x/=i;
cnt++;
}
}
if(x>1){
cnt++;
}
return cnt;
}
int main(){
ll t;
cin>>t;
while(t--){
int a,b,k;
cin>>a>>b>>k;
ll ka=fj(a),kb=fj(b);
if(k==1){
if((a%b==0||b%a==0)&&a!=b){
cout<<"YES";
}
else{
cout<<"NO";
}
}
else{
if(ka+kb<k){
cout<<"NO";
}
else{
cout<<"YES";
}
}
pr;
}
return 0;
}
G. Gift Set
1 题目描述
你有 x 个 x个 x个红糖和 y y y个蓝糖,现在你需要用这些糖果做一些礼品盒,但规定每个礼品盒里必须有 a a a个红糖、 b b b个蓝糖或 b b b个红糖、 a a a个蓝糖。现在求他最多能做成多少个礼品盒。
2 大体思路
通过二分搜索寻找一个最大的礼品盒数量
m
i
d
mid
mid ,使得在该数量下,红糖和蓝糖的搭配满足题目要求。
首先处理特殊情况:如果
a
a
a 等于
b
b
b ,直接输出
m
i
n
(
x
/
a
,
y
/
a
)
min(x/a, y/a)
min(x/a,y/a) 。
调整输入数据,确保
x
<
=
y
x <= y
x<=y 且
a
<
=
b
a <= b
a<=b 。初始化二分搜索的上下界,
l
l
l 为 0,
r
r
r 为
y
y
y 。通过二分搜索,每次取中间值
m
i
d
mid
mid ,调用函数确定是否能制作出
m
i
d
mid
mid 个礼品盒。函数中计算红糖和蓝糖的最大最小数量,确保能够满足糖果数量的要求。如果红糖最大数量不小于蓝糖最小数量,则当前
m
i
d
mid
mid 值有效,将
l
l
l 调整到
m
i
d
mid
mid 。否则,需要减小
m
i
d
mid
mid 的值,将
r
r
r 调整到
m
i
d
−
1
mid - 1
mid−1 。重复以上步骤,直到
l
l
l 大于
r
r
r ,输出最终结果
l
l
l 。
3 AC代码
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
ll x,y,a,b;
int check(int mid){
int l=ceil(1.0*(x-b*mid)/(a-b));
int r=floor(1.0*(y-a*mid)/(b-a));
l=max(l,0);
r=min(r,mid);
return l<=r;
}
void solve(){
cin>>x>>y>>a>>b;
if(a==b){
cout<<min(x/a,y/a);
return;
}
if(x>y){
swap(x,y);
}
if(a>b){
swap(a,b);
}
ll l=0,r=y;
while(l<r){
ll mid=(l+r+1)>>1;
if(check(mid)){
l=mid;
}
else{
r=mid-1;
}
}
cout<<l;
}
int main(){
ll t;
cin>>t;
while(t--){
solve();pr;
}
return 0;
}