CF1023B题解
CF1023B题解
题意
题目的意思浅显易懂:就是有 n 个物品,第 i 件物品价值为 i,问只取其中两个物品,价值能打到 k 的方案数有几个。
思路
首先先看数据范围,1≤n,k≤1014,本蒟蒻的暴力梦破裂了,只好用用小学学的数学。
我们知道:若 x+y=z,则 (x−s)+(y+s)=z(s 可以为任意实数,而本题视为非负整数)。
于是:
- 若 k≡0(mod2),则答案就为 min(k÷2−1,n−k÷2)。
- 若 k≡1(mod1),则答案就为 min(k÷2,n−k÷2)。
- 若 2×n−1<k,则无解,输出 0。
下面就来解释一下上面的分类讨论:
- 为啥要用 min 函数?
答:因为 k 可能是奇数,我们取了中间的两个数,一共有 1∼k÷2−1 配 k÷2∼k,要选出可以配对的数量就是两组数中小的那一组的数量。
- 为啥若 2×n−1<k,就无解呢?
答:因为每件物品是唯一的,也就是说只能取一次。所以最大的价值就是 2×n−1,要是 k 比这个价值还要大的话,绝对无解。
总结
- 要开 long long,不开 long long 见祖宗。
- 要特判。
- 要一点点的小学数学基础。
- 需要取小(min 函数)。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long n,k;
int main(){
scanf("%lld %lld",&n,&k);
if(2*n-1<k) printf("0");//无解的情况
//为啥无解呢?
//因为每件物品是唯一的,也就是说只能取一次。
//所以最大的价值就是2*n-1,要是k比这个价值还要大的话,绝对无解。
else if(k%2==0) printf("%lld",min(k/2-1,n-k/2));
//一定要取小的!
//因为k可能是奇数,我们取了中间的两个数,一共有1~k/2-1配k/2~k,要选出可以配对的数量就是两组数中小的那一组的数量。
else printf("%lld",min(k/2,n-k/2));
//与上面同理。
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现