您的位置:首页 > 其它

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

2017-09-20 21:27 281 查看
这题kscla课间给我的,我依然一天想不出来。

题面

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

一步一步化简,有x+yxy=1n!

接着xy−x∗n!−y∗n!=0

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

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

若将(n!)2分解质因数(n!)2=pk11∗pk22∗pk33...

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

根据现学kscla的套路,我们可以枚举质数i,i在n!中出现的次数为∑k=1n⌊nik⌋由于每个数只可能是一个质数的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
,num;
bool b
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: