题目描述
给定一个等差数列,第一项是a, 从第二项开始,每项与前一项的差都是一个定值b。如果用数学形式来表示,那么可以表示成 a + b × x , 其中 x≧0,且是整数。例如: a = 1, b=2, 那么这个等差数列就是:1,3,5,7,9…
再给定一个等比数列,第一项是c, 从第二项开始,每项是前一项的d倍。如果用数学形式来表示等比数列,则是 c ×(dy)。 其中 y≧0, 且是整数。例如: c = 2, d = 3, 那么这个等比数列就是:2,6,18,54…
你的任务是计算在1至upperBound内的正整数,有多少正整数是“合法”的?
所谓的“合法”是指:该整数属于上面给定的等差数列的某项或者属于等比数列的某项,或者既属于等差数列的项也属于等比数列的项
输入
一行,5个整数,分别是a,b,c,d,upperBound。
(1≤a,b,c,upperBound≤10^12, 1≤d≤10^5。)
对于80%的数据,1≤upperBound≤1000000。
输出
一个整数,表示“合法”正整数的个数。
分析
首先看到题目数据大小,一看就知道不能数组储存或者什么繁琐的循环了,所以我们要寻找公式。
思路:先求等差数列个数,然后求等比数列个数,将其中重复的去掉。
首先等差数列的个数显然很容易求:
(upperbound-a)/b+1
这个可以略过
然后就是等比了,求个数自己思考,然后重复的去掉就是这样一个公式,不用二分查找什么的:
(等比数列中的数-a)mod b=0,这样这个数就和等差里面的重合了。
啦啦啦~
#include <iostream>
#include <cstdio>
using namespace std;
long long ub,a,b,c,d,s,k[101],i,l;
int main()
{
scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&ub);
if (ub>=a)
{
s=(ub-a)/b;
s++;
}
if (d==1)
{
if ((((c-a)%b!=0)&&(c<=ub)||(c<a)&&(c<=ub))) s++;
}
else
{
l=1;
k[1]=c;
while (k[l]*d<=ub)
{
l++;
k[l]=k[l-1]*d;
}
s=s+l;
for (i=1;i<=l;i++) if ((k[i]-a>=0)&&(k[i]-a)%b==0) s--;
}
printf("%lld",s);
return 0;
}