数论素数筛之 樱花(详细分析)

题目背景

又到了一年樱花盛开的时节。Vani 和妹子一起去看樱花的时候,找到了一棵大大的樱花树,上面开满了粉红色的樱花。Vani 粗略估计了一下,一共有足足 n!n! 片花瓣。

Vani 轻柔地对她说:“你知道吗?这里面的一片花瓣代表着你,我从里面随机摘一片,能和你相遇的概率只有 1/n!1/n! 那么小。我该是多么的幸运,才让你今天这么近地站在我面前。相信我,我一定会把这亿万分之一的缘分变为永远。”

粉红的樱花漫天飞舞,妹子瞬间被 Vani 感动了。她轻轻地牵起了他的手,和他相依而坐。这时,她突然看到田野的尽头也长着两棵樱花树,于是慢慢地把头靠在 Vani 的肩上,在他耳边低语:“看到夕阳里的那两棵樱花树了吗?其中一棵树上的一片花瓣是你,另一棵树上的一片花瓣是我,如果有人从这棵摘下一片,从那棵采下一瓣,我们相遇的概率会不会正好是 1/n!1/n! 呢?”

Vani 的大脑飞速运作了一下,立即算出了答案。正要告诉妹子,她突然又轻轻地说:“以前你总是说我数学不好,但是这种简单的题我还是会算的。你看假如左边那棵树上有 xx 片花瓣,右边那个有 yy 片花瓣,那么我们相遇的概率不就是 1/x+1/y1/x+1/y 么,不过有多少种情况能使它正好可以等于 1/n!1/n! 呢?这个你就帮我算一下吧~”

显然,面对天然呆的可爱妹子,Vani 不但不能吐槽她的渣数学,而且还要老老实实地 帮她算出答案哦。

题目描述

数论素数筛之 樱花(详细分析)_第1张图片

输入格式
输入只有一行一个整数,表示 n。

输出格式
输出一行一个整数表示正整数解的组数

算法分析

这道题跟樱花有什么关系

第一次看这道题感觉没有任何的思路,当看了题解过后才明白这是一到数学题。

首先,这道题只有从这个等式入手,所以先通分。
所以得到:

y + x = x y n ! y+x=\frac{xy}{n!} y+x=n!xy

之后再化简一下:
( y + x ) ∗ n ! = x y (y+x)*n!=xy (y+x)n!=xy
然后就到了很多人都想不到的一步,当然也是最重要的一步配方


n ! n! n! 2 2 2 + ( y + x ) ∗ n ! − x y = n ! +(y+x)*n!-xy=n! +(y+x)n!xy=n!


在组合一下:


( x − n ! ) ( y − n ! ) = (x-n!)(y-n!)= (xn!)(yn!)= n ! n! n! 2 2 2

所以原式就变为了一个 A ∗ B = n ! A*B=n! AB=n!形式的等式,于是这道题就可以转换为 n ! n! n! 2 2 2 可以分解为几个A·B的+形式。

进一步可以转换为 n ! n! n! 2 2 2 中有几个质数,题解就出来了。

代码很好打,主要是很难想到。

代码

#include
#include
#include
using namespace std;
const int M=1e6+5;
const int Mod=1e9+7;
long long pre[M];
bool flag[M];
long long Prime_xian(long long n){
	long long k=0;
	for(long long i=2;i<=n;i++){
		if(!flag[i]){
			pre[++k]=i;
		}
		for(long long j=1;j<=k&&pre[j]*i<=n;j++){
			flag[pre[j]*i]=1;
			if(i%pre[j]==0)
				break;
		}
	}
	return k; 
}
int main(){
	long long n;
	scanf("%lld",&n);
	long long k=Prime_xian(n);
	long long ans=1;
	for(long long i=1;i<=k;i++){
		long long tot=0;
		for(long long j=pre[i];j<=n;j*=pre[i])
			tot+=n/j;
		ans*=(tot*2+1)%Mod;
		ans%=Mod;
	}
	printf("%lld",ans);
	return 0;
}

注意:开 l o n g l o n g longlong longlong,最好用线筛。

数论素数筛之 樱花(详细分析)_第2张图片

你可能感兴趣的:(数论,素数筛)