[bzoj2721] [Violet 5] 樱花

Description

求不定方程 \(\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}\) 的正整数解 \((x,y)\) 的对数。

Input

一个整数 \(n\)

Output

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

Sample Input

2

Sample Output

3

HINT

\(30\%\) 满足 \(n \leq 100\)
\(100 \%\) 满足 \(n \leq 10^6\)


题解

推一推就出来啦~
不妨设 \(x \leq y\)
原方程变形可得 \(y=\frac{n!x}{n!-x}\)
\(z=n!-x\) ,则 \(y=\frac{n!(n!-z)}{z}\)
要求 \(y\) 为整数,所以 \(z \mid n!(n!-z)\)

\(z\) 分两种情况讨论:

  1. \(z \mid n!\) 那没得说
  2. \(z\not\mid n!\) :设 \((n!,z)=g1\) , 那么 \(\frac{z}{g1} \mid (n!-z)\)
    又因为 \(\frac{z}{g1} \mid z\) ,所以 \(\frac{z}{g1} \mid n!\) ,即 \(z \mid (n!)^2\)

于是这道题就是求 \((n!)^2\) 的约数个数,分解质因数,然后指数加一连乘。


代码

\(get\) 到了新技能(虽然不是第一次了):分解质因数更快的技巧——线性筛素数,记下每个数最小质因子的序号。

#include<cstdio>
#include<iostream>
#include<algorithm>

#define Mod 1000000007

using namespace std;

const int N = 1000005;
typedef long long ll;

int n,m;
int p[N],pnum,prime[N],mn[N];
void getp(){
	for(int i=2;i<=n;i++) p[i]=1;
	for(int i=2;i<=n;i++){
		if(p[i]) prime[pnum++]=i,mn[i]=pnum-1;
		for(int j=0;j<pnum && (ll)prime[j]*i<=n;j++){
			p[prime[j]*i]=0; mn[prime[j]*i]=j;
			if(i%prime[j]==0) break;
		}
	}
}
int c[N];
void cal(int x){
	while(x!=1){
		c[mn[x]]++;
		x/=prime[mn[x]];
	}
}

int main()
{
	scanf("%d",&n);
	
	getp();
	for(int i=2;i<=n;i++) cal(i);
	
	int ans=1;
	for(int i=0;i<pnum;i++) ans=((ll)ans*(c[i]*2+1))%Mod;
	printf("%d\n",ans);
	
	return 0;
}
posted @ 2018-10-24 21:08  秋千旁的蜂蝶~  阅读(149)  评论(0编辑  收藏  举报