CF1023B题解

CF1023B题解

题意

题目的意思浅显易懂:就是有 \(n\) 个物品,第 \(i\) 件物品价值为 \(i\),问只取其中两个物品,价值能打到 \(k\) 的方案数有几个。

思路

首先先看数据范围,\(1\le n,k\le 10^{14}\),本蒟蒻的暴力梦破裂了,只好用用小学学的数学。

我们知道:若 \(x+y=z\),则 \((x-s)+(y+s)=z\)\(s\) 可以为任意实数,而本题视为非负整数)。

于是:

  1. \(k\equiv0\pmod 2\),则答案就为 \(\min(k\div2-1,n-k\div2)\)
  2. \(k\equiv1\pmod 1\),则答案就为 \(\min(k\div2,n-k\div2)\)
  3. \(2\times n-1<k\),则无解,输出 \(0\)

下面就来解释一下上面的分类讨论:

  1. 为啥要用 \(\min\) 函数?

答:因为 \(k\) 可能是奇数,我们取了中间的两个数,一共有 \(1\sim k\div2-1\)\(k\div2\sim k\),要选出可以配对的数量就是两组数中小的那一组的数量。

  1. 为啥若 \(2\times n-1<k\),就无解呢?

答:因为每件物品是唯一的,也就是说只能取一次。所以最大的价值就是 \(2\times n-1\),要是 \(k\) 比这个价值还要大的话,绝对无解。

总结

  1. 要开 long long,不开 long long 见祖宗。
  2. 要特判。
  3. 要一点点的小学数学基础。
  4. 需要取小(\(\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;
} 
posted @ 2025-01-29 15:26  naroto2022  阅读(20)  评论(0)    收藏  举报