cf 729 C
[link] <Problem - C - Codeforces>
题意
f(k) == x , 找到和k最小互质的数x, 输入一个n,求1 到 n中f(k)的和
题解
1 到 n中能被x整除的数由多少个 ?
x的倍数 均可被整除
n / x == d //最多到x的d倍
x, 2x, 3x, …… , dx 均成立,故有d个
lcm:最小公倍数,一堆数的最小基元
gcd:最大公约数,两数的最大交集
gcd(a, b) = d, lcm (a, b) = a * b / d
f(k) = x 等价于 (1,2 …, x - 1) | k
A = n / lcm(1 – x - 1) f(k) 至少是x的数
B = n / lcm(1 – x ) f(k) 至少是x + 1 的数
f(k) = x 的所有数就是 A - B
贡献是i的数在贡献是i - 1的时候贡献了i - 1所以只需要一个叠加,找到贡献为i的数每一个贡献都是1即可
f(k) = x 中 x一定是 1 2 3 4 5 … 递增出现的
枚举到i,则至少为i的数目为n / lcm(1,2 ……, i - 1).
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
#include <cmath>
#include <stack>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const int N = 2e5 + 10, M = 1100, INF = 0x3f3f3f3f, P = 131;
const LL mod = 1e9 + 7;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int n, m, k;
int dist[N];
int last[N];
bool st[N];
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a * b / gcd(a, b);
}
int main (){
int t;
cin >> t;
while (t --) {
LL n;
cin >> n;
int res = 0;
for (LL x = 1, i = 1; x <= n; x = lcm(x, i), i ++ )
res = (res + n / x) % mod;
cout << res << endl;
}
return 0;
}
1万+

被折叠的 条评论
为什么被折叠?



