You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
2.4 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int mod = 1000000007;
signed main() {
int m;
while (cin >> m && m) {
if (m == 1) {
cout << "0" << endl;
// 边界需要特别注意本题的左边界是1
// 表示的含义是小于1并且与1不互质的数的加法和当然是0。
// 在做题时,先想正常思路,然后再思考一下边界是不是用特判。
continue;
}
int n = m; // 复制出来进行质因数分解
// 分解质因数
vector<int> p;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
p.push_back(i);
while (n % i == 0) n = n / i;
}
}
if (n > 1) p.push_back(n);
// 容斥原理
int s = 0;
for (int i = 1; i < (1 << p.size()); i++) {
int cnt = 0;
int t = 1;
for (int j = 0; j < p.size(); j++) {
if (i >> j & 1) {
cnt++;
t *= p[j];
}
}
/* t:质因子的累乘积
cnt:
2,246810....
3,3691215....
6.23,61218....
*/
int num = (m - 1) / t; // 题目要求比m小的数字中也就是[1~m-1]这些数字中有多少个数是t的倍数呢?是(m-1)/t个。
/* 这些数字,首个是t,第二个是t*2,最后一个是t*num
(+)*/2
~
*/
int tmp = (t + t * num) * num / 2;
if (cnt & 1) // 奇数的加
s += tmp;
else // 偶数的减
s -= tmp;
}
cout << s % mod << endl; // 取模输出
}
}