2017 Multi-University Training Contest
来源:互联网 发布:网络教育比函授贵吗 编辑:程序博客网 时间:2024/05/24 06:22
点击打开题目链接
先打表筛选1~1e6内的素数,L,R最多到1e12,然后一个数是素数是这样定义的,如果n是素数,则2~(int)sqrt(n),都不能被n整除。
所以我们筛选素数只需要筛选到sqrt(1e12)范围就好。
其次,任何一个正整数x,都可以分解成若干个素数幂的积。小学学的分解质因子的方法就是这样的。
则 x = (p1^m1)*(p2^m2)*(p3^m3)*.....*(pn^mn); 其中p1,p2,p3...pn都是素数,m1,m2,m3...mn都是幂指数。
则 x 的因子个数d(x) = (m1+1)*(m2+1)*(m3+1)....(mn+1);
这和这些素因子的排列组合有关,举个例子:
例如 12 = 2×2×3
则 12的因子个数为 1 ×(2+1)×(1+1) = 3*2 = 6
12的因子有: 1 2 3 4 6 12 可以看出答案是正确的。那么为什么会是这样的。
这主要是和这些质因子的组合有关。12 由两个2,和一个3连乘得到
则组合情况有:0个2和0个3乘 1
1个2和0个3乘 2
2个2和0个3乘 4
0个2和1个3乘 3
1个2和1个3乘 6
2个2和1个3乘 12
对于x^k = ((p1^m1)*(p2^m2)*(p3^m3)*.....*(pn^mn))^k;
x^k = (p1^m1*k)*(p2^m2*k)*(p3^m3*k)*.....*(pn^mn*k);
则x^k的因子个数d(x^k) = (m1*k+1)*(m2*k+1)*(m3*k+1)*.....*(mn*k+1);
因为读过《基础数论》这本书,这些结论都知道,就是比赛的时候,求完素数表示,一直都时对每一个数进行分解质因数,
最后导致一直超时,方法不合适,怎么改最后都超时,比赛后看他们都是对某个素数,直接将其倍数直接筛过,这样的确快很多,
只怪自己太笨,不懂得变通,又签到了一场比赛。
AC代码:
#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>using namespace std;typedef long long LL;const int mod = 998244353;const int maxn = 1000100;int prime[maxn]; ///素数表LL a[maxn];LL yinzi[maxn];int num;void create_table(){ memset(a,0,sizeof(a)); ///0代表是素数 for(int i = 2; i <= sqrt(maxn); i++) { for(int j = 2*i; j <= maxn; j+=i) { if(a[j]==0) a[j] = 1; } } num = 0; for(int i = 2; i <= maxn; i++) { if(a[i]==0) { prime[num++] = i; } }}/**由于left和right值比较大,所以存他们的相关信息存不下,而left和right差距不超过1e6,因此hash一下,将其散列到0~1e6内**/void Hash(LL left,LL right){ /// for(LL i = left; i <= right; i++) { yinzi[i-left] = 1; a[i-left] = i; }}void solve(LL left,LL right,int k){ for(int i = 0; i<num && prime[i]<=sqrt(right*1.0); i++) { LL start,ccount; if(left%prime[i]==0) start = left; else start = left/prime[i]*prime[i]+prime[i]; ///求起点 for(LL j = start; j <= right; j += prime[i]) { ccount = 0; ///记录prime[i]的幂 while(a[j-left]%prime[i]==0) { ccount++; a[j-left] = a[j-left]/prime[i]; } yinzi[j-left] = ((yinzi[j-left]%mod)*((ccount*k+1)%mod))%mod; } } LL ans = 0; for(int i = 0; i <= right-left; i++) { if(a[i]!=1) ///代表是素数 { ans = (ans+(yinzi[i]*(k+1))%mod)%mod; } else { ans = (ans+yinzi[i])%mod; } } cout<<ans<<endl;}int main(){ int t,k; LL left,right; create_table(); ///打素数表 cin>>t; while(t--) { cin>>left>>right>>k; Hash(left,right); solve(left,right,k); } return 0;}
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- #2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- #2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 影子寄存器
- css层叠样式表
- 人物名字上莫名有个称号怎么办
- 12000字揭秘阿里连环炮面试
- hdu6052To my boyfriend(子矩阵计数处理)
- 2017 Multi-University Training Contest
- 倒角距离匹配
- google GMS认证和搭建CTS 环境一
- UVALive
- 二级制代码扫描工具
- 二维数组按照其内层数组的某个键值排序
- 在Ubuntu中添加用户
- Android O 新特性和行为变更总结
- 快速了解一个行业的秘籍,你值得拥有