hdu--6069--Counting Divisors

来源:互联网 发布:淘宝家具店招图片 编辑:程序博客网 时间:2024/05/29 19:50

Counting Divisors

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 2947    Accepted Submission(s): 1084


Problem Description
In mathematics, the function d(n) denotes the number of divisors of positive integer n.

For example, d(12)=6 because 1,2,3,4,6,12 are all 12's divisors.

In this problem, given l,r and k, your task is to calculate the following thing :

(i=lrd(ik))mod998244353

 

Input
The first line of the input contains an integer T(1T15), denoting the number of test cases.

In each test case, there are 3 integers l,r,k(1lr1012,rl106,1k107).
 

Output
For each test case, print a single line containing an integer, denoting the answer.
 

Sample Input
31 5 11 10 21 100 3
 

Sample Output
10482302
 

Source
2017 Multi-University Training Contest - Team 4

题意:d(i)表示i的因子个数;给出l,r,k。求出(i=lrd(ik))mod998244353

解题思路:根据约数个数定理得出:n=p1^c1*p2^c2*.....*pn^cn;

可得:d(n)=(c1+1)*(c2+1)*.....*(cn+1);

进一步:d(n^k)=(c1*k+1)*(c2*k+1)*.....*(cn*k+1);

d(n)里的n取值范围为1--10^12;要判断n是不是素数,只需要打1--10^6的素数表。

如果n是素数,那么他的贡献为(k+1),如果n不是素数,就用表内的素数进行分解;

具体做法是遍历已经打印好的素数表prime[maxn],另外开一个数组a,存放l到r,对应的下标为0到r-l;

遍历prime[i]时,先找到a数组内第一个能整除prime[i]的元素a[j],并用prime[i]对它进行分解,直到除不尽。

此后,每次a的下标加prime[i]个,做到消除a内以prime[i]为因子的数。

最后只要 a[i]不等于1,则其一定剩下的是一个大于 10^6的素数了。

代码:


 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 998244353;
const int maxn = 1000009;
bool Isprime[maxn];       ///素数表1
LL prime[maxn];           ///素数表2
LL a1[maxn], sum[maxn];
int cnt;
LL l, r, k;
void Prime()
{
    ///打印素数表,Isprime[ ]和prime[ ];
    cnt = 0;
    memset(Isprime, truesizeof(Isprime));
    Isprime[1] = false;
    for(int i = 2 ; i < maxn ; i++)
    {
        if(Isprime[i])
        {
            prime[cnt++] = i;
            for(int j = 2 ; i * j < maxn ; j++)
                Isprime[i * j] = false;
        }
    }
}

int main()
{
    Prime();
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%lld%lld%lld", &l, &r, &k);
        for(int i = 0; i <= r - l; i++)
        {
            sum[i] = 1///sum是要做乘法的,初值为1
            a1[i] = i + l; ///对应存储l--r的值;
        }

        for(int i = 0; i < cnt; i++)
        {
            int x;
            if(l % prime[i] != 0)
                x = 1;
            else if(l % prime[i] == 0)
                x = 0;
            LL fir = (l / prime[i] + x) * prime[i]; ///fir是从l开始第一个能整除prime[i]的

            for(LL j = fir; j <= r; j += prime[i]) ///每个j都能整除prime[i]
            {
                LL res = 0;
                while(a1[j - l] % prime[i] == 0)
                {
                    res++;
                    a1[j - l] /= prime[i];
                }///一直除下去,让数变小,找到prime[i]的幂值
                sum[j - l] = (sum[j - l] * ((res * k + 1) % mod)) % mod; ///sum[j-l]乘一下,取模
            }
        }
        LL ans = 0;
        for(int i = 0; i <= r - l; i++)
        {
            if(a1[i] != 1)
            {
                sum[i] = (sum[i] * (k + 1)) % mod; ///经过一系列除法没除到1,说明1e6内的素数分解不了,那么它就是一个大素数
            }

            ans = (ans + sum[i]) % mod;
        }
        printf("%lld\n", ans);
    }

    return 0;
}




原创粉丝点击