【51nod 1189】阶乘分数——阶乘质因数分解

先对原式子进行一个变形:

1/n!=1/x+1/y=(x+y)/xy--->n!*(x+y)=xy

xy-(x+y)*n!=0--->xy-(x+y)*n!+n!2=n!2--->(x-n!)*(y-n!)=n!2

那么如果我们能够求出n!2的约数个数,对于每个约数加上n!即可作为x或y。

若n!=a1p1+a2p2+...+akpk,则n!的约数总数为∏(pi+1)

因为是n!2,所以每个pi要乘上2.

因为对于每个约数a,都必将有唯一的一个b与它对应使得a*b=n!,所以如果不考虑x和y的大小和重复关系的话答案就是约数个数。

但是这里加上了限制条件,因此要除掉重复的部分,即需将答案加1除以2向下取整(加一是为了防止将完全平方数的平方根除去)

对于n!的质因数分解,则应该先把n以内的质数筛出,求出每个质数的阶数即可。

例:对10!分解质因数

10以内的质数有2,3,5,7.

2:10/2=5,10/4=2,10/8=1,阶数为2+5+1=8;

3:10/3=3,10/9=1,阶数为3+1=4;

5:10/5=2,阶数为2;

7:10/7=1,阶数为1;

所以10!=28*34*52*7.

代码:

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 typedef long long LL;
 4 const LL mod=1e9+7;
 5 const int N=1e6+10;
 6 int n,prime[N],cnt=0;
 7 bool vis[N];
 8 void make_prime(){
 9     for(int i=2;i<=n;i++){
10         if(!vis[i])prime[++cnt]=i;
11         for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
12             vis[i*prime[j]]=1;
13             if(i%prime[j]==0)break;
14         }
15     }
16 }
17 LL ans=1,ni=(mod+1)/2;
18 int main(){
19     scanf("%d",&n);
20     make_prime();
21     for(int i=1;i<=cnt;i++){
22         LL p1=0;
23         for(LL j=prime[i];j<=n;j*=prime[i])p1+=n/j;
24         ans=(ans*(2*p1+1)%mod)%mod;
25     }
26     printf("%lld",(ans+1ll)*ni%mod);
27     return 0;
28 }
51nod 1189

 

posted @ 2017-10-27 06:52  Child-Single  阅读(1391)  评论(0编辑  收藏  举报