64 lines
2.4 KiB
C++
64 lines
2.4 KiB
C++
#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,那么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; // 取模输出
|
||
}
|
||
} |