BZOJ2721: [Violet 5]樱花
Description
Input
Output
Sample Input
1439
Sample Output
102426508
HINT
题解Here!
一道恶心数论题。。。
这个分母看得很烦人,于是将方程左边通分:$$\frac{x+y}{xy}=\frac{1}{n!}$$
十字相乘:$$n!(x+y)=xy$$
移项:$$xy-n!(x+y)=0$$
两边同时加上$(n!)^2$得:$$(n!)^2-n!(x+y)+xy=(n!)^2$$
左边因式分解:$$(x-n!)(y-n!)=(n!)^2$$
设$a=x-n!,b=y-n!$,则有:$$ab=(n!)^2$$
由唯一分解定理可知:$$n!=p_1^{num_1}\times p_2^{num_2}\times...\times p_k^{num_k}$$
那么有:$$(n!)^2=p_1^{2num_1}\times p_2^{2num_2}\times...\times p_k^{2num_k}$$
也就是:$$ab=p_1^{2num_1}\times p_2^{2num_2}\times...\times p_k^{2num_k}$$
因为$n!$是确定的,所以确定了$a,b$,就能确定$x,y$。
并且只要确定了$a$,就能确定$b$!
我们知道,$a$是$(n!)^2$的因式。
那么$a$的个数为:$$(2num_1+1)(2num_2+1)...(2num_k+1)$$
于是最后的答案即为:$$(2num_1+1)(2num_2+1)...(2num_k+1)\mod (10^9+7)$$
线性筛搞一遍,然后把$num_i$全部计算出来,最后统计答案即可。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 1000010 #define MOD 1000000007 using namespace std; int n; int k=0,prime[MAXN],num[MAXN],val[MAXN]; bool np[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } void make(){ int m=n; for(int i=2;i<=m;i++){ if(!np[i]){ prime[++k]=i; val[i]=i; } for(int j=1;j<=k&&prime[j]*i<=m;j++){ np[prime[j]*i]=true; val[prime[j]*i]=prime[j]; if(i%prime[j]==0)break; } } for(int i=1;i<=m;i++) for(int j=i;j!=1;j/=val[j]) num[val[j]]++; } void work(){ long long ans=1; for(int i=1;i<=n;i++)ans=(long long)1LL*ans*((num[i]<<1)+1)%MOD; printf("%lld\n",ans); } int main(){ n=read(); make(); work(); return 0; }