P9611 题解
jackzhangcn2013 · · 题解
题目大意
从题目可知,本题要求求出
题目分析
我们可以将这个问题分解为两个问题,变成求
首先,如果正着做很难的话,我们可以考虑反着做。
对于一个数
根据这个原理,我们可以写出一个时间复杂度为
#include<bits/stdc++.h>
#define int long long
const int N = 1e5+5;
const int Mod = 1e9+7;
using namespace std;
int l, r;
int f(int n)
{
int cnt = 0;
for(int i = 1; i <= n; i++)
{
cnt += n / i;
}
return cnt;
}
signed main()
{
cin >> l >> r;
cout << f(r) - f(l - 1) << endl;
return 0;
}
看来我们要把时间复杂度降到
可以想到,对于每一个数,他的因数必然是成对的(平方数除外),那么我们只需要遍历到
那么现在我们要考虑哪些部分会重复。
我们以
| 数字 | 因数 |
|---|---|
我们的贡献统计是这样的:
| 数字 | 贡献数字对 |
|---|---|
通过观察重复的标红部分,我们发现每个数刚好重复了
于是我们便可以完成最后的代码:
AC Code
#include<bits/stdc++.h>
#define int long long
const int N = 1e5+5;
const int Mod = 1e9+7;
using namespace std;
int l, r;
int f(int n)
{
int cnt = 0, sqr = sqrt(n);
for(int i = 1; i <= sqr; i++)
{
cnt += n / i;
}
return cnt * 2 - sqr * sqr;
}
signed main()
{
cin >> l >> r;
cout << f(r) - f(l - 1) << endl;
return 0;
}