#include 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 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,那么2,4,6,8,10,....需要加上 枚举到的组合中只有数字3,那么3,6,9,12,15,....需要加上 枚举到的组合中中6.有数字2,3,那么6,12,18,....需要减去 */ 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; // 取模输出 } }