签到题
题目背景
这是一道签到题!
建议做题之前仔细阅读数据范围!
题目描述
我们定义一个函数: qiandao ( x ) \operatorname{qiandao}(x) qiandao(x) 为小于等于 x x x 的数中,与 x x x 不互质的数的个数。
这题作为签到题,给出 l l l 和 r r r,求出:
∑ i = l r qiandao ( i ) m o d 666623333 \sum_{i=l}^r \operatorname{qiandao}(i)\bmod 666623333 i=l∑rqiandao(i)mod666623333
输入格式
一行两个整数, l l l、 r r r。
输出格式
一行一个整数表示答案。
样例 #1
样例输入 #1
233 2333
样例输出 #1
1056499
样例 #2
样例输入 #2
2333333333 2333666666
样例输出 #2
153096296
提示
- 对于 30 % 30\% 30% 的数据, l , r ≤ 1 0 3 l,r\leq 10^3 l,r≤103。
- 对于 60 % 60\% 60% 的数据, l , r ≤ 1 0 7 l,r\leq 10^7 l,r≤107。
- 对于 100 % 100\% 100% 的数据, 1 ≤ l ≤ r ≤ 1 0 12 1 \leq l \leq r \leq 10^{12} 1≤l≤r≤1012, r − l ≤ 1 0 6 r-l \leq 10^6 r−l≤106。
问题链接: P3601 签到题
问题分析: 数论问题,不解释。
参考链接: (略)
题记: (略)
AC的C++语言程序如下:
/* P3601 签到题 */
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const LL MOD = 666623333;
// 欧拉筛法
const int N = 1000000;
bool isprime[N + 1];
LL primes[N / 3];
int pcnt = 0;
void eulersieve(void)
{
memset(isprime, true, sizeof isprime);
isprime[0] = isprime[1] = false;
for(int i = 2; i <= N; i++) {
if(isprime[i])
primes[pcnt++] = i;
for(int j = 0; j < pcnt && i * primes[j] <= N; j++) { //筛选
isprime[i * primes[j]] = false;
if(i % primes[j] == 0) break;
}
}
}
LL phi[N + 1], bp[N + 1];
int main()
{
eulersieve();
LL l, r;
cin >> l >> r;
for (LL i = l; i <= r; i++)
phi[i - l] = bp[i - l] = i;
for (LL i = 0; i < pcnt && primes[i] * primes[i] <= r; i++) {
LL start = l / primes[i];
if (l % primes[i] != 0) start++;
for (LL j = start * primes[i]; j <= r; j += primes[i]) {
phi[j - l] = phi[j - l] / primes[i] * (primes[i] - 1);
while (bp[j - l] % primes[i] == 0) bp[j - l] /= primes[i];
}
}
LL ans = 0;
for (LL i = l; i <= r; i++) {
if (bp[ i - l] != 1)
phi[i - l] = phi[i - l] / bp[i - l] * (bp[i - l] - 1);
ans = (ans + (i - phi[i - l])) % MOD;
}
cout << ans;
return 0;
}