一名苦逼的OIer,想成为ACMer

Iowa_Battleship

BZOJ2721或洛谷1445 [Violet]樱花

BZOJ原题链接

洛谷原题链接

其实推导很简单,只不过我太菜了想不到。。。又双叒叕去看题解
简单写下推导过程。
原方程:$$\dfrac{1}{x} + \dfrac{1}{y} = \dfrac{1}{n!}$$
通分:$$\dfrac{x + y}{xy} = \dfrac{1}{n!}$$
十字相乘:$$(x + y) \times n! = xy$$
\((x + y) \times n!\)移到右项:$$xy - (x + y) \times n! = 0$$
两边同时加上\((n!)^2\):$$(n!)^2 - (x + y) \times n! + xy = (n!) ^ 2$$
左项因式分解:$$(x - n!) \times (y - n!) = (n!) ^ 2$$
\(a = x - n!, b = y - n!\),则方程变为:$$ab = (n!) ^ 2$$
显然确定\(a\)就能确定\(b\),也能确定\(x, y\),所以\(a\)有几组解即是原方程\(x, y\)解的组数。
而根据算术基本定理,\(n! = \prod \limits _{i = 1} ^ k p_i ^ {c_i}\),所以\((n!) ^ 2 = \prod \limits _{i = 1} ^ k p_i ^ {2c_i}\)
再根据约数个数定理,\((n!) ^ 2\)的约数个数即是\(\prod \limits _{i = 1} ^ k (2c_i + 1)\),这就是答案

#include<cstdio>
using namespace std;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
int pr[N];
bool v[N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
int main()
{
	int i, s = 1, c, n, l = 0;
	long long j;
	n = re();
	v[0] = v[1] = 1;
	for (i = 1; i <= n; i++)
	{
		if (!v[i])
			pr[++l] = i;
		for (j = 1; j <= l; j++)
		{
			if (i * pr[j] > n)
				break;
			v[i * pr[j]] = 1;
			if (!(i % pr[j]))
				break;
		}
	}
	for (i = 1; i <= l; i++)
	{
		c = 0;
		for (j = pr[i]; j <= n; j *= pr[i])
			c = (1LL * c + n / j) % mod;
		s = 1LL * s * (c << 1 | 1) % mod;
	}
	printf("%d", s);
	return 0;
}

posted on 2018-11-01 16:52  Iowa_Battleship  阅读(152)  评论(0编辑  收藏  举报

导航