HDU 6069 Counting Divisors —— 2017 Multi-University Training 4

Counting Divisors

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

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 :

Input

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

In each test case, there are 3 integers l,r,k(1≤l≤r≤1012,r?l≤106,1≤k≤107).

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

题目大意:d(i)是 i 的因数个数,让我们求 l<=i<=r 时,d(i^k)之和.

思路:对一个数n=p1t1*p2t2*...*pntn, pi是n的质因数。则n的因数个数是(t1+1)*(t2+1)*...*(tn-1+1)*(tn+1), 易得i^k的因数个数是(k*t1+1)*(k*t2+1)*...*(k*tn+1),那么接下来就是要对 i 进行质因数分解了。 在打表打出质因数后,分解时对于一个质数P, 在[l , r]区间内所有能整除P的数进行质因数分解,这样能保证不会有多余时间花在搜索质因数上,这种做法类似筛法。具体见代码。

AC代码(标程):

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<stdio.h>
 6 #define it (p-l)
 7 using namespace std;
 8 typedef long long LL;
 9 const LL MOD=998244353;
10 const long long MAXN=1000005;
11 long long prime[MAXN],tot=0;
12 bool isPrime[MAXN];
13 LL k,num[MAXN],res[MAXN];
14 void getprime(){
15     memset(isPrime, true, sizeof(isPrime));
16     for(int i=2;i<MAXN;i++){
17         if(isPrime[i]){
18             prime[++tot]=i;
19         }
20         for(int j=1;j<=tot;j++){
21             if(i*prime[j]>MAXN) break;
22                 isPrime[i*prime[j]]=false;
23             if(i%prime[j]==0) break;
24         }
25     }
26     return ;
27 }
28 LL cal(LL l, LL r)
29 {
30     LL ans=0,tmp,cnt;
31     for(int i=1;i<=tot;i++)
32     {
33         LL p=(l+prime[i]-1)/prime[i]*prime[i];
34         while(p<=r){
35             cnt=0;
36             while(num[it]%prime[i]==0){
37                 num[it]/=prime[i];
38                 cnt++;
39             }
40             res[it]=res[it]*(k*cnt+1)%MOD;
41             p+=prime[i];
42         }
43     }
44     for(LL p=l;p<=r;p++){
45         if(num[it]==1)
46             ans+=res[it];
47         else
48             ans+=res[it]*(k+1);
49         ans%=MOD;
50     }
51     return ans;
52 }
53 int main()
54 {
55     int T;
56     LL l,r;
57     getprime();
58     scanf("%d", &T);
59     while(T--)
60     {
61         scanf("%lld %lld %lld", &l, &r, &k);
62         for(LL p=l;p<=r;p++){
63             res[it]=1;
64             num[it]=p;
65         }
66         LL res=cal(l, r);
67         printf("%lld\n", res);
68     }
69 }
时间: 2024-10-11 06:57:09

HDU 6069 Counting Divisors —— 2017 Multi-University Training 4的相关文章

hdu 6069 Counting Divisors(求因子的个数)

Counting Divisors Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 3170    Accepted Submission(s): 1184 Problem Description In mathematics, the function d(n) denotes the number of divisors of

第四场 hdu 6069 Counting Divisors (逆向思维)

http://acm.hdu.edu.cn/showproblem.php?pid=6069 题目大意:求 i 从 l 到 r 中 i 的k次方的因子数之和. 解题思路:我们可以知道一个数有因子,则这个数的因子一定是若干个质数因子排列组合得到的.我们首先要得到10^6中的素数,然后它的因子数量是 相同质因子数量+1 的乘积,所以我们能够想到从 l 到 r 枚举每一个i得到其 相同质因子数量+1 的乘积 的累加和.但是这样在枚举时会发现有一些质数是并不是所求的 i 的因子,所以我们应该反过来考虑,

HDU 6069 Counting Divisors(唯一分解定理+因子数)

http://acm.hdu.edu.cn/showproblem.php?pid=6069 题意: 思路: 根据唯一分解定理,$n={a_{1}}^{p1}*{a2_{}}^{p2}...*{a_{m}}^{pm}$,那么n的因子数就是 n的k次方也是一样的,也就是p前面乘个k就可以了. 先打个1e6范围的素数表,然后枚举每个素数,在[ l , r ]寻找该素数的倍数,将其分解质因数. 到最后如果一个数没有变成1,那就说明这个数是大于1e6的质数.(它就只有0和1两种选择) 1 #includ

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

题意:...就题面一句话 思路:比赛一看公式,就想到要用到约数个数定理 约数个数定理就是: 对于一个大于1正整数n可以分解质因数: 则n的正约数的个数就是 对于n^k其实就是每个因子的个数乘了一个K 然后现在就变成了求每个数的每个质因子有多少个,但是比赛的时候只想到sqrt(n)的分解方法,总复杂度爆炸,就一直没过去,然后赛后看官方题解感觉好妙啊! 通过类似素数筛法的方式,把L - R的质因子给分解,就可以在O(nlogn)的时间之内把所以的数给筛出来. 代码: /** @xigua */ #i

hdu 6069 Counting Divisors

题意:给出求L,R 之间的数的K次方的因子数之和 思路:打表求出1~10^6之间的素数,枚举[L,R]之间素数的倍数,然后按算数基本定理求出因子个数和.处理过后[L,R]之间的数要么是1,要么是一个素数,再次根据算数基本定理计算因子个数和. #include<bits/stdc++.h> #define MAXSIZE 1000015 #define INF 0x3f3f3f3f #define LL long long #define MOD 998244353 using namespac

HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9

/* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问两串是否匹配 分析: dp[i][j] 代表B[i] 到 A[j]全部匹配 然后根据三种匹配类型分类讨论,可以从i推到i+1 复杂度O(n^2) */ #include <bits/stdc++.h> using namespace std; const int N = 2505; int t;

HDU 6168 - Numbers | 2017 ZJUT Multi-University Training 9

/* HDU 6168 - Numbers [ 思维 ] | 2017 ZJUT Multi-University Training 9 题意: .... 分析: 全放入multiset 从小到大,慢慢筛 */ #include <bits/stdc++.h> using namespace std; const int N = 125250; int n, s[N]; int a[N], cnt; multiset<int> st; multiset<int>::it

Counting Divisors HDU - 6069

Counting Divisors HDU - 6069 题意:给定区间[a,b]和k,求xk有多少因子(x属于[a,b]),求和. 题解:http://blog.csdn.net/zlh_hhhh/article/details/76680641 a.b最大可达到1e12,但是b-a<1e6. 一开始愚蠢的一个一个分解然后去求有多少因子然后求和,范围那么大裸裸的超时啊! 可以枚举素数,对每一个素数,把区间内所有可以分解的进行分解. 最后再求和. 1 #include <bits/stdc++

hdu 1396 Counting Triangles (递推)

Counting Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2012    Accepted Submission(s): 966 Problem Description Given an equilateral triangle with n the length of its side, program to