CF900D Unusual Sequences
显然我们需要 \(x|y\),不妨令 \(n={y\over x}\),则变成求 \(\gcd(a_1,a_2,...,a_n)=1\) 且 \(\sum a_i=n\) 的个数。
令 \(f(n)\) 为答案,考虑反演。设 \(g(n)\) 为满足后面一个条件的序列个数,由插板法知: \(g(n)=2^{n-1}\),我们可以得到式子:
\[g(n)=\sum_{d|n} f(n)
\]
我们可以莫比乌斯反演一下:
\[f(n)=\sum_{d|n}\mu(d)g({n\over d})
\]
\(n\) 的因数数量很少,可以通过。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100005, mod = 1e9 + 7;
inline int power(int a, int b) {
int t = 1, y = a, k = b;
while (k) {
if (k & 1) t = (1ll * t * y) % mod;
y = (1ll * y * y) % mod; k >>= 1;
} return t;
}
inline int mu(int x) {
int t = x, ret = 1;
for (int i = 2; i * i <= t; ++i) {
if (t % i) continue;
if (!((t / i) % i)) return 0;
t /= i; ret = -ret;
} if (t != 1) ret = -ret; return ret;
}
int x, y;
int main() {
scanf("%d%d", &x, &y);
if (y % x) return puts("0") & 0;
int ans = 0, n = y / x;
for (int i = 1; i * i <= n; ++i) {
if (n % i) continue;
ans += mu(i) * power(2, n / i - 1);
if (ans >= mod) ans -= mod; if (ans < 0) ans += mod;
if (i * i != n) {
ans += mu(n / i) * power(2, i - 1);
if (ans >= mod) ans -= mod; if (ans < 0) ans += mod;
}
} printf("%d", ans);
return 0;
}