一道很有意思的思维题,题目如下:
泽泽顺利拿到了魔法石,想要利用魔法石干掉伏地魔,但是奇洛挡在了他面前。不过,因为有魔法石,奇洛的魔法斗不过泽泽,于是他出了一个数学题,想要难倒泽泽。无奈,泽泽的数学很糟糕。于是,他找到了你,希望你帮忙解决这一问题,从而干掉伏地魔。奇洛出的题目是:他给出两个整数a,b(1<=a,b<=10000000),要你求出a到b的所有数的约数的个数的和。
例如:他给出的是1和6,那么:
1的约数只有1个,即1。
2的约数个数为2,1和2。
3的约数个数为2,4的约数个数为3,5的约数个数为2,6的约数个数为4.
所以,这个问题的答案为1+2+2+3+2+4=14。
输入
两个整数a,b。
输出
仅包含一个整数,即为最后的答案。
输入样例复制
1 6
输出样例复制
14
说明
【数据规模】
对于50%的数据
1<=a,b<=1000;
对于80%的数据
1<=a,b<=1000000;
对于100%的数据
1<=a,b<=10000000;
很显然,此题要我们求出n~m之间的所有约数,下面提供三种做法
1、暴力枚举:枚举n~m之间的所有约数之和,但n最大达10000000,会严重超时,期望分40
2、筛选法,类似于埃式筛选法,首先,由于n只达10000000,所以我们可以用一个数组来表示每个数,那么对于每个数来说(1除外,1只有一个约数),它都有两个约数,分别是1和它本身,那么我们就可以得到一个公式,(n-m+1)*2,这就是没处理之前的所有n~m之间的约数之和。接下来,我们就要对n~m之间的数来处理,这里就要用到埃式筛选法的思想,列如n=1,m=6,我们用一个for来从2枚举每一个数,那么当i=2时,
2*2=4,2*3=6,这时我们可以发现6和4中都含有约数2,只要我们将当前的数组加一,那么当循环结束,每个数约数的个数就在数组中了
3·优化筛选法,可能一部分人想到了第2种,但是还是超时了,其原因就在于多了一个10000000次的循环来算总合,那么可以将两者合并在一起吗,其实是可以的,只要我们在筛选数是加上if(i*j<=b&&i*j>=a)就可以了
这样就不会超时了
最后给上核心代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b;
ll ys(ll x)
{
ll s=0;
for(ll i=1;i<=x;i++)
s+=x/i;
return s;
}
int main()
{
ll a,b;
cin>>a>>b;
cout<<ys(b)-ys(a-1);
return 0;
}