[关闭]
@Chilling 2017-08-06T01:29:53.000000Z 字数 1834 阅读 1028

HDU-6069: Counting Divisors (素筛 + 思维)

数论


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 .

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的因子个数为多少,如i等于12,那么d(i)就等于6,因为12的因子有1,2,3,4,6,12。题目输入l,r,k,意思是在l到r的区间里的每个数为n,求,累加起来即可。

分析:一个数的因子个数:将这个数质因子分解后,每个质因子的指数加一乘起来即为答案。比如。题中求,又因为一个数n的因子除了自己本身之外,其他质因子一定不超过,因此只需要将小于的素数求出。然后,对于区间的每一个数,如果依次枚举将其质因子分解,则会超时。那么我们枚举质因子,能够整除质因子的数只有区间里该质因子的倍数,因此就可以跳着枚举。最后剩下的部分就是超过的质数,只可能是0个或1个。


  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int maxn = 1e6 + 5;
  5. const int mod = 998244353;
  6. int prime[maxn];
  7. LL num[maxn], ans[maxn];
  8. void primeform (int n)
  9. {
  10. prime[0] = 2;
  11. int cnt = 1;
  12. for (int i = 3; i < n; i++)
  13. {
  14. int flag = 1;
  15. for (int j = 2; j * j <= i; j++)
  16. if (i % j == 0)
  17. {
  18. flag = 0;
  19. break;
  20. }
  21. if (flag) prime[cnt++] = i;
  22. }
  23. }
  24. void getans (LL l, LL r, LL k)
  25. {
  26. for (int i = 0; prime[i] <= r && prime[i]; i++)
  27. {
  28. LL now = l % prime[i] == 0 ? 0 : prime[i] - l % prime[i]; //找到起点
  29. for (LL j = now; j <= r - l; j += prime[i])
  30. {
  31. LL cnt = 0;
  32. while (num[j] % prime[i] == 0)
  33. {
  34. num[j] /= prime[i];
  35. cnt++;
  36. }
  37. ans[j] = (ans[j] * ( (cnt * k + 1) % mod) ) % mod;
  38. }
  39. }
  40. for (int i = 0; i <= r - l; i++) //超过根号r的质因子
  41. if (num[i] != 1)
  42. ans[i] = (ans[i] * (k + 1)) % mod;
  43. }
  44. void clr(LL l, LL r)
  45. {
  46. for (int i = 0; i <= r - l; i++)
  47. ans[i] = 1, num[i] = i + l;
  48. }
  49. int main()
  50. {
  51. primeform (1e6);
  52. int t;
  53. scanf ("%d", &t);
  54. while (t--)
  55. {
  56. LL l, r, k, ret = 0;
  57. scanf ("%lld %lld %lld", &l, &r, &k);
  58. clr(l, r);
  59. getans (l, r, k);
  60. for (int i = 0; i <= r - l; i++)
  61. ret = (ret + ans[i]) % mod;
  62. printf ("%lld\n", ret);
  63. }
  64. return 0;
  65. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注