恭 介 的 法 则 ( r u l e ) 恭介的法则(rule) 恭介的法则(rule)
题目链接: j z o j 3456 jzoj\ 3456 jzoj 3456
题目
终于,在众亲们的奋斗下,最终 b o s s boss boss 恭介被关进了库特设计的密室。正当她们松了一口气时,这个世界却发生了天翻覆地的变化:地面开始下沉,天空开始变成血红色,海水沸腾……一幅世界末日的图景。美鱼从她手中的古籍《若山牧水诗歌集》中发现了原因: 白 鸟 は か な し か ら ず や 空 の 青 海 の あ を に も 染 ま ず た だ よ ふ 白鸟は かなしからずや 空の青 海のあをにも 染まずただよふ 白鸟はかなしからずや空の青海のあをにも染まずただよふ 。大 ( x i a ) (xia) (xia)意 ( s h u o ) (shuo) (shuo)就是狡猾的恭介在创造这个世界的时候就篡改了法则。而这个法则的起源,就是一只生死之间的猫。这个猫被关在一个黑盒子里,盒子里有两个毒气罐,如果有任意一个毒气罐被打开那么猫将会被杀死,法则也能得到纠正。然而外界能控制的仅仅是这两个毒气罐被打开的概率。假设第一个毒气罐被打开的概率为 1 / x 1/x 1/x,第二个毒气罐为 1 / y 1/y 1/y( x x x, y y y 为正整数),那么当两个概率和为 1 / ( n ! ) 1/(n!) 1/(n!)时,猫将会被莫名其妙地杀死。现在美鱼想知道,有多少对(x,y)可以让猫被莫名其妙杀死。
输入
一行,一个正整数 n n n
输出
一行,满足题意的 ( x , y ) (x,y) (x,y)对数。
样例输入
6
样例输出
135
数据范围
对于 30 % 30\% 30%的数据 n < = 6 n\!<=\!6 n<=6
对于 60 % 60\% 60%的数据 n < = 50 n\!<=\!50 n<=50
对于 100 % 100\% 100%的数据 n < = 700000 n\!<=\!700000 n<=700000
思路
这道题是一道数论题。
(下面的推论与解法是看了某位大佬的博客做出来的)
由题意可以得出这个式子:
1
x
+
1
y
=
1
n
!
\dfrac{1}{x}+\dfrac{1}{y}=\dfrac{1}{n!}
x1+y1=n!1
两边都乘一个
x
x
x,就得到这个:
1
+
x
y
=
x
n
!
1+\dfrac{x}{y}=\dfrac{x}{n!}
1+yx=n!x
移项得到这个:
1
=
x
n
!
−
x
y
1=\dfrac{x}{n!}-\dfrac{x}{y}
1=n!x−yx
然后通分得到这个:
1
=
x
∗
(
y
−
n
!
)
y
∗
n
!
1=\dfrac{x*(y-n!)}{y*n!}
1=y∗n!x∗(y−n!)
把
y
∗
n
!
y*n!
y∗n!移到左边,就是这个:
y
∗
n
!
=
x
∗
(
y
−
n
!
)
y*n!=x*(y-n!)
y∗n!=x∗(y−n!)
再把右边的
(
y
−
n
!
)
(y-n!)
(y−n!)移过去,就变成了这一个:
y
∗
n
!
y
−
n
!
=
x
\dfrac{y*n!}{y-n!}=x
y−n!y∗n!=x
即:
x
=
y
∗
n
!
y
−
n
!
x=\dfrac{y*n!}{y-n!}
x=y−n!y∗n!
又因为这三个数(
x
x
x,
y
y
y和
n
n
n)都是正整数,就可以得到
y
∗
n
!
y*n!
y∗n!是
y
−
n
!
y-n!
y−n!的倍数,而且
y
>
n
!
y>n!
y>n!。
那我们再设一个正整数
k
k
k,让
k
=
y
−
n
!
k=y-n!
k=y−n!,那
y
=
k
+
n
!
y=k+n!
y=k+n!,那么我们前面的式子就变成了这个:
x
=
(
n
!
+
k
)
∗
n
!
(
n
!
+
k
)
−
n
!
x=\dfrac{(n!+k)*n!}{(n!+k)-n!}
x=(n!+k)−n!(n!+k)∗n!
分解一下就是:
x
=
n
!
2
+
k
∗
n
!
k
x=\dfrac{n!^2+k*n!}{k}
x=kn!2+k∗n!
那我们要让
x
x
x是正整数,就要让
n
!
2
k
\dfrac{n!^2}{k}
kn!2都是正整数(因为
x
=
k
∗
n
!
k
x=\dfrac{k*n!}{k}
x=kk∗n!一定是正整数)
那就变成求 n ! 2 n!^2 n!2有多少个因数。
那我们让
k
z
h
i
=
n
k^{zhi}=n
kzhi=n,那我们通过证明可以得到有
z
h
i
∗
2
+
1
zhi * 2 + 1
zhi∗2+1种方案。
(因为平方就是
n
∗
n
n*n
n∗n,就是
k
z
h
i
∗
k
z
h
i
k^{zhi}*k^{zhi}
kzhi∗kzhi即
k
2
∗
z
h
i
k^{2 * zhi}
k2∗zhi,那从不选到选
2
∗
z
h
i
2 * zhi
2∗zhi个,就一共有
z
h
i
∗
2
+
1
zhi * 2 + 1
zhi∗2+1种方案了)
那就素数筛选法,求
n
n
n素数做。
(但是因为答案有“一”点大,要压位高精,我这里压了
8
8
8位)
代码
#include<cstdio>
#define ll long long
#define mo 100000000
using namespace std;
ll n, len, ans[700001];
bool in[700001];
void cheng(ll now) {//高精乘
ll jin = 0;
for (ll i = 1; i <= len; i++) {
ans[i] = ans[i] * now + jin;
jin = ans[i] / mo;
ans[i] %= mo;
}
while (jin) {
ans[++len] = jin;
jin = ans[len] / mo;
ans[len] %= mo;
}
}
int main() {
len = 1;
ans[1] = 1;//初始化
scanf("%lld", &n);//读入
ll an = 1;
for (ll i = 2; i <= n; i++)
if (!in[i]) {//找到质数
ll num = n, zhi = 0, kind;
while (num >= i) {//求出指数
num /= i;
zhi += num;
}
kind = 2 * zhi + 1;
if (an * kind > mo) {//需要压位
cheng(an);
an = kind;
}
else an *= kind;
for (ll j = 1; j * i <= n; j++)
in[j * i] = 1;
}
if (an != 1) cheng(an);//剩下的
printf("%lld", ans[len]);//输出
for (ll i = len - 1; i >= 1; i--)
printf("%08lld", ans[i]);//输出
return 0;
}