2721: [Violet 5]樱花 思路题 线性筛素数
2016-02-15 09:20
531 查看
思路还是挺巧妙的。。我数论还是太弱了。
首先容易发现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写过一次了)。
我们可以根据阶乘的定义来算出约数个数,对于素数就直接计算,对于合数,我们可以在线性筛的时候记录下它的最小质因子(因为每个合数只会被它的最小质因子筛掉一次,因而保证了线性),从而求出每个合数的所有质因子。最后统计答案,不要忘记有个平方所以出现了两次。
首先容易发现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 1000000007 using 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; }
相关文章推荐
- __attribute__ 机制
- CentOS 7 下查看IP地址
- qt5.2中文显示为乱码问题
- ECshop 迁移到 PHP7版本时遇到的兼容性问题
- C语言,移动鼠标获得当鼠标当前位置坐标
- UserControl 的一个值得注意的问题 [属性" * "的代码生成失败.错误是:"程序集"*.Version=1.0.0.0,Culture=neutral,..........无标记为序列化"
- 《你不常用的c#之二》:略谈GCHandle
- 实例解析iOS应用多线程开发中NSthread类的用法
- [LeetCode 050] Pow(x, n)
- s7-1200PLC的PID调节问题
- 读jquery.cookie.js源码学到的几个技巧
- 用Telnet发送HTTP请求
- 单元测试NUnit教程
- Android 查看pdf文档——PDFView
- 中产的焦虑
- bootstrap分页
- 登录名称
- MySQL集群搭建详解
- try和finally执行顺序
- 反编译与混淆