HDOJ 6069 素数筛法(数学)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ 6069 素数筛法(数学)相关的知识,希望对你有一定的参考价值。

Counting Divisors

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


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
 
思路:先将1000005以内的素数打表(素数筛法O(n)).  然后将每个数拆成S=p1^a1*p2*^a2...*pn^an 的形式则 d(S)=(1+a1)*(1+a2)....*(1+an);
实现方法:1.用num[] 存下当前拆分后剩下的数字
     2.用ans[i]存下第i个数字此时的已拆分的累乘结果
     3.将素数从小到大扫一遍,对[l,r]每个数字进行拆分,逐一更新ans[i]的值
代码:
 1 #include<bits/stdc++.h>
 2 
 3 typedef long long ll;
 4 using  namespace std;
 5 
 6 const int N=1e6+5;
 7 const int inf=1e9;
 8 const int mod=998244353;
 9 
10 ll l,r,k;
11 bool v[N];
12 ll ans[N];
13 ll num[N];
14 int pri[N];
15 int pcnt;
16 void init()
17 {
18     pcnt = 0;//素数筛
19     for(int i = 2; i <= N; i++)
20     {
21         if(!v[i])
22             pri[pcnt++] = i;
23         for(int j = 0; j < pcnt && pri[j] <= N/i; j++)
24         {
25             v[i*pri[j]] = 1;
26             if(i % pri[j]==0) break;
27         }
28     }
29 }
30 void f()
31 {
32     for(ll i=l;i<=r;i++)//初始化记录数组
33         num[i-l]=i,ans[i-l]=1;
34 }
35 int main()
36 {
37     int t;
38     init();
39     scanf("%d",&t);
40     while(t--)
41     {
42         scanf("%lld%lld%lld",&l,&r,&k);
43         f();
44         for(int i=0;i<pcnt&&pri[i]<=1000000;i++){//限制质因子大小
45             ll p=pri[i];
46             ll d=l/p+(l%p>0);
47             if(d==1) d=2;//l<=p 的情况在最后判断处理
48             for(ll j=d*p;j<=r;j+=p){
49                 ll cnt=0;
50                 while(num[j-l]%p==0){
51                     num[j-l]/=p;
52                     cnt++;
53                 }
54                 ans[j-l]=(ans[j-l]%mod)*((1+k*cnt)%mod)%mod;
55             }
56         }
57         ll sum=0;
58         for(ll i=l;i<=r;i++){
59             if(num[i-l]>1)//还存在一个大于1000000的因子,再乘上k+1
60                 sum=(sum+ans[i-l]*(k+1))%mod;
61             else
62                 sum=(sum+ans[i-l])%mod;
63         }
64         printf("%lld\n",sum);
65     }
66 
67 }

 

 

 

 

以上是关于HDOJ 6069 素数筛法(数学)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6069 Counting Divisors(区间素数筛法)

HDU6069 Multi-4 素数筛

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

数学基础素数线性筛法--欧拉筛法模板普通筛法的优化

数学数论素数的线性筛法

hdu6069 多校Counting Divisors