2721: [Violet 5]樱花 思路题 线性筛素数

来源:互联网 发布:触摸屏网站源码 编辑:程序博客网 时间:2024/05/03 20:06

思路还是挺巧妙的。。我数论还是太弱了。


首先容易发现x,y一定>n!,那么不妨设y=n!+z,那么x=n!+n!^2/z。
我们要求z的数量,也就是求n!^2的约数个数。
若n!^2=pa^a1*p2^a2…pn^an,那么n!^2的约数个数为(a1+1)(a2+1)*…(an+1)。(好像昨天在一篇blog写过一次了)。
我们可以根据阶乘的定义来算出约数个数,对于素数就直接计算,对于合数,我们可以在线性筛的时候记录下它的最小质因子(因为每个合数只会被它的最小质因子筛掉一次,因而保证了线性),从而求出每个合数的所有质因子。最后统计答案,不要忘记有个平方所以出现了两次。

#include<iostream>#include<cstdio>#define ll long long #define p 1000000007using namespace std;int n;ll ans=1;int prime[1000005],pos[1000005],cnt[1000005];bool flag[1000005];inline void get_prime(){    for (int i=2;i<=n;i++)    {        if (!flag[i]) prime[++prime[0]]=i,pos[i]=prime[0];        for (int j=1;j<=prime[0]&&i*prime[j]<=n;j++)        {            flag[i*prime[j]]=1; pos[i*prime[j]]=j;            if (i%prime[j]==0) break;        }    }}int main(){    scanf("%d",&n);    get_prime();    for (int i=1;i<=n;i++)     {        int tmp=i;        while (tmp!=1) cnt[pos[tmp]]++,tmp/=prime[pos[tmp]];    }    for (int i=1;i<=prime[0];i++) ans=ans*((2*cnt[i]+1)%p)%p;    cout << ans << endl;}       
0 0
原创粉丝点击