题解: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\) 啥事情!
首先,分四种情况:
- \(k>n\),显然无解。
- \(k=n\),这个也很显然,直接摆一个商品为 \(1\) 的价格即可。
- \(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\) 解决!
- 对于剩下的 \(k>\lceil\frac{n}{2}\rceil\) 的情况,是可以证明无解的。
证明:首先要是第一个人商品不为 \(1\) 要买最多的物品数肯定第一个商品价格为 \(2\)。接下来分类讨论两种情况:
- \(n\) 是偶数,则最终选出来的物品数最多为 \(\frac{n}{2}\leqslant\lceil\frac{n}{2}\rceil\)。
- \(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;
}