题解:CF1951D Buying Jewels

CF1951D 题解

题面

原题传送门

题意

题意翻译成数学语言大概是这样的:

给定 \(n,k(1\leqslant n,k\leqslant 10^{18})\),构造一个长度不超过 \(60\) 的正整数序列 \(a_1,a_2,a_3,\cdots,a_n\),记 \(b_0=n,c_i=\lfloor\frac{b_{i-1}}{a_i}\rfloor,b_i=b_{i-1}\bmod a_i\),序列 \(c\) 满足 \(\begin{aligned}\sum_{i=1}^{m}c_i=k\end{aligned}\)。若有合法解请输出 YES 及其中一种,否则输出 NO

思路

这题真的很想说一句是一个诈骗题,看到 \(60\) 自然地想到了二进制,后来发现好像似乎只要输出两个数字,犹豫的提交一下就过了……没 \(60\) 啥事情!

首先,分四种情况:

  1. \(k>n\),显然无解。
  2. \(k=n\),这个也很显然,直接摆一个商品为 \(1\) 的价格即可。
  3. \(k\leqslant \lceil\frac{n}{2}\rceil\),这个就需要点小头脑构造了,首先 \(a_1=n-k+1\),则 \(c_1=\frac{b_0}{a_1}=\frac{n}{n-k+1}=1\),而 \(b_1=b_0\bmod a_1=k-1\),接下来 \(a_2=1,c_2=k-1,c_1+c_2=k\) 解决!
  4. 对于剩下的 \(k>\lceil\frac{n}{2}\rceil\) 的情况,是可以证明无解的。

证明:首先要是第一个人商品不为 \(1\) 要买最多的物品数肯定第一个商品价格为 \(2\)。接下来分类讨论两种情况:

  1. \(n\) 是偶数,则最终选出来的物品数最多为 \(\frac{n}{2}\leqslant\lceil\frac{n}{2}\rceil\)
  2. \(n\) 是奇数,则最终选出来的物品数最多为 \(\frac{n}{2}+1\leqslant\lceil\frac{n}{2}\rceil\)

综上,当 \(k>\lceil\frac{n}{2}\rceil\) 时无解。

所以,快去打代码过了这道题吧~

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
ll T,n,k; 
void write(ll n){if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
int main(){
	T=read();while(T--){
		n=read();k=read();
		if(n==k) printf("YES\n1\n1\n");
		else if(k<=(n+1)/2) printf("YES\n2\n%lld 1\n",n-k+1);
		else printf("NO\n");
	}
	return 0;
}
posted @ 2025-01-29 15:53  naroto2022  阅读(11)  评论(0)    收藏  举报