CF1023B题解
CF1023B题解
题意
题目的意思浅显易懂:就是有 \(n\) 个物品,第 \(i\) 件物品价值为 \(i\),问只取其中两个物品,价值能打到 \(k\) 的方案数有几个。
思路
首先先看数据范围,\(1\le n,k\le 10^{14}\),本蒟蒻的暴力梦破裂了,只好用用小学学的数学。
我们知道:若 \(x+y=z\),则 \((x-s)+(y+s)=z\)(\(s\) 可以为任意实数,而本题视为非负整数)。
于是:
- 若 \(k\equiv0\pmod 2\),则答案就为 \(\min(k\div2-1,n-k\div2)\)。
- 若 \(k\equiv1\pmod 1\),则答案就为 \(\min(k\div2,n-k\div2)\)。
- 若 \(2\times n-1<k\),则无解,输出 \(0\)。
下面就来解释一下上面的分类讨论:
- 为啥要用 \(\min\) 函数?
答:因为 \(k\) 可能是奇数,我们取了中间的两个数,一共有 \(1\sim k\div2-1\) 配 \(k\div2\sim k\),要选出可以配对的数量就是两组数中小的那一组的数量。
- 为啥若 \(2\times n-1<k\),就无解呢?
答:因为每件物品是唯一的,也就是说只能取一次。所以最大的价值就是 \(2\times 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;
}

浙公网安备 33010602011771号