BZOJ 3930 - [CQOI2015]选数
Published on 2016-08-14描述
在 内选出 个数(可以重复),问所选的数的最大公约数恰好为 的方案总数。
保证 。
分析
因为 ,所以任意两个数 的 ,为什么?
证明:假设 ,将 写成 ,则 ,所以 即 ,所以 。
另外,本题还可以使用莫比乌斯反演,不过时间很卡,详见Po姐的博客。
代码
// Created by Sengxian on 8/14/16. // Copyright (c) 2016年 Sengxian. All rights reserved. // BZOJ 3930 递推 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int ReadInt() { static int n, ch; n = 0, ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) n = (n << 3) + (n << 1) + ch - '0', ch = getchar(); return n; } const int maxn = 100000 + 3, modu = 1000000007; inline int mod_pow(ll a, int b) { ll ans = 1; while (b) { if (b & 1) ans = ans * a % modu; a = a * a % modu; b >>= 1; } return ans; } int n, K, l, r, f[maxn]; int main() { scanf("%d%d%d%d", &n, &K, &l, &r); l = ceil((double)l / K), r /= K; for (int i = maxn - 1; i >= 1; --i) { static int ll, rr; ll = ceil(double(l) / i), rr = r / i; if (rr - ll + 1 <= 0) {f[i] = 0; continue;} f[i] = (mod_pow(rr - ll + 1, n) - (rr - ll + 1) + modu) % modu; for (int j = i << 1; j < maxn; j += i) f[i] = (f[i] - f[j] + modu) % modu; } if (l == 1) f[1]++; printf("%d\n", f[1]); return 0; }