Bzoj2721 [Violet]樱花(筛法)

题面

题解

首先化一下式子

$$ \frac 1x+\frac 1y=\frac 1{n!} \Rightarrow \frac {x+y}{xy}=\frac 1{n!} \Rightarrow (x+y)n!=xy \\ \Rightarrow(n!-x)+(n!-y)=(n!)^2 $$

看到最后一个式子,由于$n!$是唯一确定的,所以只要确定了$x$,$y$也是确定的,而且是唯一确定的一组$(x,y)$。

根据唯一分解定理,$n!=p_1^{k_1}p_2^{k_2}...p_m^{k_m}\Rightarrow(n!)^2=p_1^{2k_1}p_2^{2k_2}...p_m^{2k_m}$

所以$x$的取值方案数为$\prod_{i=1}^m(2k_i+1)$

线性筛一下就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::swap; using std::sort;
typedef long long ll;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

const int N = 1e6 + 10, Mod = 1e9 + 7;
int n, k[N], cnt, prime[N], id[N], ret = 1;
inline int sqr(int x) { return x * x; }
inline void add(int &x) { x = (x + 1) == Mod ? 0 : (x + 1); }

int main () {
	scanf("%d", &n);
	memset(id, -1, sizeof id);
	for(int i = 2; i <= n; ++i) {
		if(id[i]) id[i] = ++cnt, prime[cnt] = i;
		for(int j = 1; j <= cnt && i * prime[j] <= n; ++j) {
			id[i * prime[j]] = 0;
			if(!(i % prime[j])) break;
		}
	}
	for(int i = 2; i <= n; ++i) {
		int tmp = i;
		for(int j = 1; sqr(prime[j]) <= tmp; ++j)
			while(!(tmp % prime[j])) add(k[id[prime[j]]]), tmp /= prime[j];
		if(tmp > 1) add(k[id[tmp]]);
	}
	for(int i = 1; i <= cnt; ++i)
		ret = (2ll * k[i] + 1) * ret % Mod;
	printf("%d\n", ret);
    return 0;
}

 

转载于:https://www.cnblogs.com/water-mi/p/10184575.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值