一个采购员去银行兑换一张y元f分的支票,结果出纳员错给了f元y分。采购员用去了n分之后才发觉有错,于是清点了余额尚有2y元2f分,问该支票面额是多少?
输入格式:
输入在一行中给出小于100的正整数n。
输出格式:
在一行中按格式y.f
输出该支票的原始面额。如果无解,则输出No Solution
。
输入样例1:
23
输出样例1:
25.51
输入样例2:
22
输出样例2:
No Solution
解析:这道题 乍一看十分“弱智”,却隐藏着一个“深不见底”的大坑,我被卡了一晚上(别笑,maybe我确实菜鸡,卡在第一个测试点上,怎么也想不通)后来只好去百度了别人的代码,忽然有一种茅厕顿开的感觉....
首先,按照正常逻辑思维来说,我们会讨论两种情况:
1.y>n 这就意味着,我们可以推出一组方程(两个等式):
f==2y;
y-n==2f;
但是,很显然,我们可以得到这个方程是负数解,钱不可能是负的,所以(按照正常想法),我们自然可以得出一个结论:y要比n小,也就是第二种情况是必然成立的。
2.y<n 这也意味着,我们可以推出一组方程(两个等式):
f-1==2y;
100+y-n==2f;
按照正常想法,我们自然可以解出方程:y=(98-n)/3;f=2*y+1;
所以我会这样写:scanf一个n之后,if((98-n)%3!=0),那我们就可以直接判断 No solution了,因为钱的单位不管是元还是分,都不可能是小数,必然是整数。然而,然而...
第一个测试点就是不对。
所以,到底错在哪里呢?
这就要回到我们第二种情况最开始的那两个方程,当我们用掉n分之后,所剩下的2y元和2f分真的和最初的钱数有那样的一一对应的关系吗?
并不是,仔细想想平常生活中用现金买东西,我们会发现最后手里剩下的零钱是一大把的,也就是说,在银行给我们钱之后,我们没有花钱之前,我们可以保证,y分的范围一定是小于100的,但是当我们花掉n分钱后,因为在这期间有可能会产生找零的各种情况,我们最后所剩下的2f分钱有可能就是大于100的,举个栗子:n==97,最开始我们有68元,33分,花掉97分之后,我们剩下66元,136分(我们可以统一到分为单位 验证一下),那么在这种情况里,我们就不能简单地写做:f-1==2y;100+y-n==2f;
不然这会导致看似 No solution,其实是有解的情况。
我猜,这就是第一个测试点卡我的原因。
写代码时候,我们可以直接用两个for循环完事儿,就不用再管(98-n)%3是否为0,但是我觉得代码按照一定逻辑来写也是可以的,虽然看起来冗余了一些。先验证(98-n)%3是否为0,如果为0,直接算出来y和f;如果不为0,再用两个for循环去寻找我们的y和f,也就是暴力搜索。如果这都找不到,那就是 No solution了。
#include<cstdio>
#include<iostream>
using namespace std;
int y,f,n;
int main(){
scanf("%d",&n);
y=(98-n)/3;
f=2*y+1;
if((98-n)%3==0) printf("%d.%d\n",y,f);
else{
for(int i=0;i<100;i++){
for(int j=0;j<100;j++){
if((2*i*100+2*j)==(j*100+i-n)){
printf("%d.%d\n",i,j);
return 0;
}
}
}
printf("No Solution\n");
}
return 0;
}