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 :
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(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) .
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
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, true, sizeof(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; } |