hdu6069(简单数学+区间素数筛法)
2017-08-06 11:07
344 查看
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6069
题意: 给出 l, r, k.求:(lambda d(i^k))mod998244353,其中 l <= i <= r, d(i) 为 i 的因子个数.
思路:若 x 分解成质因子乘积的形式为 x = p1^a1 * p2^a2 * ... * pn^an,那么 d(x) = (a1 + 1) * (a2 + 1) * ... * (an + 1) .显然 d(x^k) = (a1 * k + 1) * (a2 * k + 1) * ... * (an * k + 1) .
但如果仅仅以此暴力求解的话是会 tle 的, 需要用下区间素数筛法并且在筛选区间内合数时将其质因分解,将 i 对答案的贡献存储到 sum 数组中,然后再遍历一次统计素数对答案的贡献并将所有贡献累加起来即可.
代码:
View Code
(∑i=lrd(ik))mod998244353
(∑i=lrd(ik))mod998244353
(∑i=lrd(ik))mod998244353
题意: 给出 l, r, k.求:(lambda d(i^k))mod998244353,其中 l <= i <= r, d(i) 为 i 的因子个数.
思路:若 x 分解成质因子乘积的形式为 x = p1^a1 * p2^a2 * ... * pn^an,那么 d(x) = (a1 + 1) * (a2 + 1) * ... * (an + 1) .显然 d(x^k) = (a1 * k + 1) * (a2 * k + 1) * ... * (an * k + 1) .
但如果仅仅以此暴力求解的话是会 tle 的, 需要用下区间素数筛法并且在筛选区间内合数时将其质因分解,将 i 对答案的贡献存储到 sum 数组中,然后再遍历一次统计素数对答案的贡献并将所有贡献累加起来即可.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define ll long long 5 using namespace std; 6 7 const int MAXN = 1e6 + 10; 8 const int mode = 998244353; 9 int prime[MAXN], tag[MAXN], tot; 10 ll sum[MAXN], gel[MAXN]; 11 12 void get_prime(void){ 13 for(int i = 2; i < MAXN; i++){ 14 if(!tag[i]){ 15 prime[tot++] = i; 16 for(int j = 2; j * i < MAXN; j++){ 17 tag[j * i] = 1; 18 } 19 } 20 } 21 } 22 23 ll Max(ll a, ll b){ 24 return a > b ? a : b; 25 } 26 27 int main(void){ 28 get_prime(); 29 ll l, r; 30 int k, t; 31 scanf("%d", &t); 32 while(t--){ 33 scanf("%lld%lld%d", &l, &r, &k); 34 for(int i = 0; i <= r - l; i++){ 35 sum[i] = 1; //sum[i]记录i+l对答案的贡献 36 gel[i] = i + l; //将所有元素放到a数组里 37 } 38 for(int i = 0; i < tot; i++){ 39 ll a = (l + prime[i] - 1) / prime[i] * prime[i]; 40 for(ll j = a; j <= r; j += prime[i]){ // 筛[l, r]内的合数 41 ll cnt = 0; 42 while(gel[j - l] % prime[i] == 0){ 43 cnt++; 44 gel[j - l] /= prime[i]; 45 } 46 sum[j - l] = sum[j - l] * (cnt * k + 1 % mode); 47 if(sum[j - l] >= mode) sum[j - l] %= mode; 48 } 49 } 50 ll sol = 0; 51 for(int i = 0; i <= r - l; i++){ 52 if(gel[i] != 1) sum[i] = sum[i] * (k + 1); 53 sol += sum[i]; 54 if(sol >= mode) sol %= mode; 55 } 56 printf("%lld\n", sol); 57 } 58 return 0; 59 }
View Code
(∑i=lrd(ik))mod998244353
(∑i=lrd(ik))mod998244353
(∑i=lrd(ik))mod998244353
相关文章推荐
- HDU6069 Counting Divisors 区间素数筛法
- Win7附带的数学输入面板让输入数学公式更简单
- poj 3468(简单线段树区间更新)
- hdu-1018-Big Number-简单数学
- SGU - 107 - 987654321 problem (简单数学!)
- FJUT 3101 Home_W的简单问题3 数学 因子和问题
- POJ 2282-The Counting Problem(组合数学_区间计数)
- 杭电ACM1220——Cube~~简单的数学题
- 动画的帧频设定和人眼生理特关系中的简单数学
- 一道简单数学题!10人有11个人算错!!
- codeforces 153 A. Points on Line 简单数学题 简单推导推导的事情
- hdu 1788 Chinese remainder theorem again((数学:简单题)
- nyoj 阶乘的0 84 (简单数学转换)
- 简单的数学与人生的复杂
- 简单数学训练—C
- NYOJ 330 一个简单的数学题
- POJ 1046(颜色映射 简单数学) 解题报告
- zzulioj--1600--直线与圆(简单数学几何)
- (hdu 简单题 128道)平方和与立方和(求一个区间的立方和和平方和)
- 【UESTC 1513 简单的数学题】