洛谷P1445(数学+画柿子+线性筛)

来源:互联网 发布:天猫抢购软件 编辑:程序博客网 时间:2024/04/29 17:42

这题kscla课间给我的,我依然一天想不出来。

题面
题意:给定n,求有多少对正整数(x,y)满足

1x+1y=1n!

一步一步化简,有

x+yxy=1n!

接着
xyxn!yn!=0

然后掏出祖传的初中数学——因式分解,变成了
(xn!)(yn!)=(n!)2

由于x,y都是正整数,故问题变成了(n!)2的约数个数。

若将(n!)2分解质因数

(n!)2=pk11pk22pk33...

ans=(k1+1)(k2+1)(k3+1)...

根据现学kscla的套路,我们可以枚举质数i,i在n!中出现的次数为
k=1nnik
由于每个数只可能是一个质数的k次方,故总复杂度是低于O(n)的。

然后就线性筛把素数找出来就搞定了,嘟嘟噜!

kscla大佬自己想到了一个炫酷的做法,点这里

#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=1001000;const LL mo=1000000007;LL n;LL prime[N],num;bool b[N];LL ans=1ll;int main(){    cin>>n;    for(LL i=2;i<=n;i++)    {        if(!b[i])        prime[++num]=i;        for(int j=1;j<=num&&prime[j]*i<=n;j++)        {            b[i*prime[j]]=1;            if(i%prime[j]==0)            break;        }    }    for(int i=1;i<=num;i++)    {        LL k=0;        LL tu=prime[i],hy=prime[i];        while(tu<=n)        {            k=(k+n/tu)%mo;            tu=tu*hy;        }        ans=ans*(2*k+1)%mo;    }    cout<<ans<<endl;    return 0;}
阅读全文
0 0
原创粉丝点击