一,题目描述
一个数是完美的,仅当它等于它的因数中比它小的所有数之和。
例如:28=1+2+4+7+14,所以 28 是完美的。
由此我们可以定义一个数的不完美值 F(N),代表 N和比 N 小的所有 N 的因数之和的差的绝对值。
例如:F(6)=|6-1-2-3|=0,
F(11)=|11-1|=10,
F(24)=|24-1-2-3-4-6-8-12|=|-12|=12。
现在给出两个正整数 A 和 B,请你求出 F(A)+F(A+1 )+...+F(B)。
输入格式
一行,两个整数 A 和 B,含义如上。
输出格式
一行,一个整数,表示 F(A)+F(A+1)+...+F(B)。
样例 #1
样例输入 #1
1 9
Copy
样例输出 #1
21
Copy
样例 #2
样例输入 #2
24 24
Copy
样例输出 #2
12
Copy
提示
【样例解释 #1】
F(1)+...+F(9)=1+1+2+1+4+0+6+1+5=21
【数据范围】
对于 100%的数据,1<= A,B<=10^7。
二,直接照题目的描述模拟
#include <bits/stdc++.h>
using namespace std;
long long s,a,b;
long long f(long long x)
{
long long ans = 1,tp = x;//ans:x的约数和
unordered_map<long long,long long> mp;
for(long long i = 2; i <= x / i; i++)
{
while(x % i == 0)
{
x /= i;
mp[i]++;
}
}
if(x > 1) mp[x]++;
for(auto p : mp)
{
long long a = p.first, b = p.second,t = 1;
while(b--) t = (t * a + 1);
ans = ans * t;
}
return abs(tp - (ans - tp));//照着题目意思算出f(x)
}
int main()
{
scanf("%lld%lld",&a,&b);
for(int i = a;i <= b;i++) s += f(i);//枚举a~b的f()之和
printf("%lld",abs(s));
return 0;
}
三,正解:
这一题我们可以用类似埃氏筛法的做法来做。怎么做呢?我们可以用一个数组s来存储1~b中的每一个数的因数和,因为一个合数可以分解为有限个质数的乘积,设一个数i(从1到sqrt(n))的j倍为x,所以就以知道i和j一定是x的约数,若i = j,那么 将i * j的因数和+= i或j 即可,也就是s[i * j] += i 就行了,否则将i * j的因数和 += i + j,也就是s[i * j] += i + j。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a,b,ans,s[20000001];
signed main()
{
scanf("%d%d",&a,&b);
for(int i = 1; i * i <= b; i++)
for(int j = i; i * j <= b; j++)
if(i == j) s[i * j] += i;
else s[i * j] += (i + j);
for(int i = a; i <= b; i++) ans += abs(i * 2 - s[i]);
cout<<abs(ans);
}