[BZOJ 2721] [Violet 5] 樱花 【线性筛】

题目链接:BZOJ - 2721

 

题目分析

题目大意:求出 1 / x + 1 / y = 1 / n! 的正整数解 (x, y) 的个数。

显然,要求出正整数解 (x, y) 的个数,只要求出使 y 为正整数的正整数 x 的个数,或者求出使 x 为正整数的正整数 y 的个数即可。

那么我们来转化一下这个式子:

通分:

(x + y) / xy = 1 / n!

n!(x + y) = xy

将 y 分离出来:

n!x = xy - n!y

n!x = (x - n!)y

y = n!x / (x - n!)

那么我们就是要求出,使 n!x / (x - n!) 为正整数的正整数 x 的个数。

我们换元,设 d = x - n! ,则 x = n! + d, 式子变为:

y = n!(n! + d) / d

y = (n!)^2 / d + n!

我们就是要求出使 (n!)^2 / d + n! 为正整数的 d 的个数,显然,d 是 (n!)^2 的任意一个因数。

于是问题转化为,求出 (n!)^2 的因数个数。

因数个数的计算公式:如果一个数的质因数分解为 x = p1^a1 * p2^a2 * ... * pn^an,那么

x 的因数个数为 (a1 + 1) * (a2 + 1) * ... * (an + 1)

我们要求出 (n!)^2 所含的每个质因数的幂次。

n! 含有的质因数就是 n 以内的所有质数,所以我们筛出 n 以内的所有因数,然后我们对于每个因数 pi ,枚举 n 以内的它的所有的倍数,然后暴力求出 1 ~ n 的所有数中,一共含有 pi 的幂次 ai 是多少。那么 (n!)^2 中含有这个质数的幂次就是 ai * 2 。

 

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

const int MaxN = 1000000 + 5, MaxP = 100000 + 5, Mod = 1000000007;

typedef long long LL;

int n, Top;
int Prime[MaxP];

bool isPrime[MaxN];

LL Ans;

int main()
{
	scanf("%d", &n);
	for (int i = 2; i <= n; ++i) isPrime[i] = true;
	isPrime[1] = false;
	for (int i = 2; i <= n; ++i)
	{
		if (isPrime[i]) Prime[++Top] = i;
		for (int j = 1; j <= Top && i * Prime[j] <= n; ++j)
		{
			isPrime[i * Prime[j]] = false;
			if (i % Prime[j] == 0) break;
		}
	}
	Ans = 1;
	int Cnt, Temp;
	for (int i = 1; i <= Top; ++i)
	{
		Cnt = 0;
		for (int j = Prime[i]; j <= n; j += Prime[i])
		{
			Temp = j;
			while (Temp % Prime[i] == 0)
			{
				Temp /= Prime[i];
				++Cnt;
			}
		}
		Ans = Ans * (LL)(Cnt * 2 + 1) % Mod;
	}
	cout << Ans << endl;
	return 0;
}

  

posted @ 2015-06-02 22:13  JoeFan  阅读(408)  评论(0编辑  收藏  举报