P4167 [Violet]樱花

题目背景

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

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

相信我,我一定会把这亿万分之一的缘分变为永远。”

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

Vani 的大脑飞速运作了一下,立即算出了答案。正要告诉妹子,她突然又轻轻地说:“以 前你总是说我数学不好,但是这种简单的题我还是会算的。你看假如左边那棵树上有 x片花

瓣,右边那个有 y 片花瓣,那么我们相遇的概率不就是1/x+1/y么,不过有多少种情况能使

它正好可以等于1/n!呢?这个你就帮我算一下吧~”

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

题目描述

求不定方程

​1/x+1/y=1/n!

的正整数解(x,y)的数目。

输入格式

一个整数n。

输出格式

一个整数,表示有多少对 (x,y) 满足题意。答案对10^9+7取模。

输入输出样例

输入 #1
2
输出 #1
3 

说明/提示

样例说明

共有三个数对(x,y)满足条件,分别是 (3,6)(4,4)和(6,3)。

数据范围与约定 对于 30% 的数据,保证n≤100。

思路

共有三个数对(x,y)满足条件,分别是 (3,6)(4,4)和(6,3)。

对(n!)^2唯一分解的时候,最暴力的做法是直接分解,也就是对每一个n,枚举每个小于sqrt(n)的质数,时间复杂度为O(sqrt(n)*)

 

但是我们不需要那么暴力

可以利用线性筛里面处理出来的数组v(v[i]是i的最小质因子)来加快我们对于每一个数唯一分解的速度

对于一个数,我们可以每次除去它的最小质因子,并且累加记录,然后对于计算后得到的结果继续除其最小质因子,直到把这个数除成1为止

这样的话,时间复杂度降为O(nlogn),这样就可以过了

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=1000010;
const int Mod=1e9+7;

int n,ans;
long long fj[N],v[N];
long long p[N],tot=0;

void work(int n) {
	memset(p,0,sizeof(p));
	memset(v,0,sizeof(v));
	tot=0;
	for(int i=2; i<=n; i++) {
		if(!v[i]) {
			v[i]=i;
			tot++;
			p[tot]=i;
		}
		for(int j=1; j<=tot; j++) {
			if(i*p[j]>n||v[i]<p[j])
				break;
			v[p[j]*i]=p[j];
		}
	}
}

int main () {
	scanf("%d",&n);
	work(n);
	for(int i=1; i<=n; i++)
		for(int j=i; j!=1; j/=v[j]) {
			++fj[v[j]];
			fj[v[j]]%=Mod;
		}
	ans=1;
	for(int i=1; i<=n; i++)
		ans=(ans*(fj[i]<<1|1))%Mod;
	printf("%lld\n",ans);
	return 0;
}

 

posted @ 2019-08-04 09:59  双子最可爱啦  阅读(304)  评论(0编辑  收藏  举报