题目描述
两年一度的欧洲杯又开始了,小海可是一个铁杆球迷,每天晚上都会到XX酒吧观看激烈的比赛,而且小海有给小费的习惯,但是他给小费是由原则的:
-
总费用必须是5的倍数;
-
小费必须占总费用的5%~10%之间(包括边界)
假设小海在酒吧的消费是A元,小海带了B元来酒吧,小海想知道他有多少种支付方案供选择。
总费用 = 消费 + 小费
输入
多组测试数据,请处理到文件结束。
对于每组测试数据:
包含两个整数A和B。
数据组数<=1000,1<=A,B<=23^1-1,A<=B。
输出
输出一个整数,代表方案数。
样例输入
4 100
23 100
样例输出
0
1
思路:
首先考虑数据较大,并且组数多,不可能使用枚举,必须考虑数学方法。
通过简单代数计算求出,x*20/19<=总消费<=x**10/9(x为消费),求出左右边界。
将边界移至以1为起点,即可把问题转化为从1到n有多少个五的倍数。
还应考虑到对原区间和变换后区间,中间包含到的5的个数会有所不同,只需模拟一下,将变换后区间变为原区间(个位相同),枚举其中包含的5的倍数。
并且考虑左边界是否为五的倍数。不需要考虑右边界,因为上面的枚举过程一定会包含右边界为五的倍数的情况。
我的弱鸡代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll a,b;
while(~scanf("%lld %lld",&a,&b)){
ll k=0;
double c=(double)a*20/19,d=(double)a*10/9;
ll y1=c,y2=d;
if(y1>b){
printf("0\n");
continue;
}
if(y2>b)
y2=b;
if(c-y1!=0&&(y1+1)<=y2)
y1++;
k=y2-y1+1;
if(y1%10!=0){
for(int i=1;i<y1%10;i++){
if((k+i)%5==0)
k+=5;
if((1+i)%5==0)
k-=5;
}
}
else{
for(int i=1;i<=9;i++){
if((k+i)%5==0)
k+=5;
if((1+i)%5==0)
k-=5;
}
}
if(y1%5==0)
k+=5;
k/=5;
printf("%lld\n",k);
}
return 0;
}
克神的神仙代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int main(){
ll A,B,l,r;
while(~scanf("%lld %lld",&A,&B)){
l=A%19==0?A/19:ceil(A/19.0);
r=min(A/9,B-A);
while(r>=1&&(A+l)%5)l++;
if(r<l)puts("0");
else printf("%lld\n",(r-l)/5+1);
}
return 0;
}
总结:
这道题想了很久,改了很多很多遍才做对,只能说自己太菜……尤其是看了克神的代码后真的无地自容。
但是还是收获了新知识新方法,nice。