首页 > 代码库 > hdu6069(简单数学+区间素数晒法)

hdu6069(简单数学+区间素数晒法)

题目链接: 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 数组中,然后再遍历一次统计素数对答案的贡献并将所有贡献累加起来即可.

 

代码:

技术分享
 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(简单数学+区间素数晒法)