codeforces 439 E. Devu and Birthday Celebration (莫比乌斯反演+组合)

题目链接:https://codeforces.com/problemset/problem/439/E

反演后求方程整数解的个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 200010;
const int M = 1000000007;

int q, n, f;
int fac[maxn], ifac[maxn];

int cnt;
int prime[100010], mu[100010], is_prime[100010];

int qsm(int i, int po){
	int res = 1;
	while(po){
		if(po & 1) res = 1ll * i * res % M;
		i = 1ll * i * i % M;
		po >>= 1;
	}
	return res;
}

int C(int x, int y){
	if(y > x) return 0;
	return 1ll * fac[x] * ifac[y] % M * ifac[x-y] % M;
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	fac[0] = 1;
	for(int i = 1 ; i <= 100000 ; ++i) fac[i] = 1ll * fac[i-1] * i % M;
	ifac[100000] = qsm(fac[100000], M-2);
	for(int i = 99999 ; i >= 0 ; --i) ifac[i] = 1ll * ifac[i+1] * (i+1) % M;
	
	mu[1] = 1;
	for(int i = 2; i <= 100000; ++i){
		if(!is_prime[i]){
			prime[++cnt] = i;
			mu[i] = -1;
		}
		for(int j = 1 ; j <= cnt && prime[j] * i <= 100000 ; ++j){
			is_prime[i * prime[j]] = 1;
			if(i % prime[j] == 0) {
				mu[i * prime[j]] = 0;
				break;
			} else {
				mu[i * prime[j]] = -mu[i];
			}
		}
	}
	
	q = read();
	for(int i = 1 ; i <= q ; ++i){
		n = read(), f = read();
		int ans = 0;
		for(int j = 1 ; j <= (int)sqrt(n+0.5) ; ++j){
			if(n % j == 0){
				if(j * f <= n) ans = ((ans + 1ll * mu[j] * C(n/j-1, f-1) % M) % M + M) % M;
				if(j * j != n){
					if(n/j * f <= n) ans = ((ans + 1ll * mu[n/j] * C(j-1, f-1) % M) % M + M) % M;
				}
			}
		}
		printf("%d
", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/15252853.html