hdu--6069--Counting Divisors

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
  
  
3 1 5 1 1 10 2 1 100 3
 

Sample Output
  
  
10 48 2302
 

Source

题意: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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值