您的位置:首页 > 其它

【HDU 6069 Counting Divisors】 + 素数筛 & 思维

2017-08-04 10:12 429 查看
Counting Divisors

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)

Total Submission(s): 1372 Accepted Submission(s): 494

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(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

Source

2017 Multi-University Training Contest - Team 4

题解 :



例如 : 对于 6 ^ 2 = 36,有 1,2,3,4,6,9,12,18,36 共 9 个因子,而 6 = 2 ^ 1 * 3 ^ 1,可以拆分成素因子相乘的形式,所以 6 ^ 2 的因子 = (1 * 2 + 1) * (1 * 2 + 1) = 9,6 ^ k = (1 * k + 1 ) * (1 * k + 1),即因子 2 的次幂 * k + 1 * 因子 3 的次幂 * k + 1, 对于 n ^ k 的因子数 = 把 n 拆分成素因子相乘的形式后,每个素因子的次幂 * k + 1,最后在相乘~

首先筛选出 1 ~ 1e6 内的素数, 题目给出 r - l <= 1e6, 可以从这个条件入手,如果直接遍历 l ~ r,内的每个数的素因数,1~1e6 有 78499 个素数,会 T, 利用 r - l <= 1e6 的条件把 l~r 压缩到一个 0 ~ (r - l)的数组里, 用素数筛的方法,用每个素数去 遍历 l ~ r 的区间,还需要一个数组记录下 l ~ r 对应位置的初始值,方便最后要判断下如果经过所有的素数整除判断后还不为 1,者这个数便是一个素数 +这个素数的贡献

AC代码:

#include<cstdio>
typedef long long LL;
const int mod = 998244353;
const int MAX = 1e6 + 10;
int vis[MAX],p[MAX],nl;
LL l,r,k,a[MAX],s[MAX];
void init(){
nl = 0;
for(int i = 2; i < MAX; i++){
if(!vis[i]) p[++nl] = i;
for(int j = 1; j <= nl; j++){
LL o = (LL) i * p[j];
if(o > MAX) break;
vis[o] = 1;
}
}
}
void solve(){
for(int i = 0; i <= r - l; i++) s[i] = 1,a[i] = l + i;
for(int i = 1; i <= nl && (LL)p[i] * p[i] <= r ; i++){
LL o = l / p[i] + (l % p[i] != 0);
for(LL j = o * p[i]; j <= r; j += p[i]){
LL w = 0;
while(a[j - l] % p[i] == 0) a[j - l] /= p[i],w++;
s[j - l] = (w * k % mod + 1) % mod * s[j - l] % mod;
}
}
LL ans = 0;
for(int i = 0; i <= r - l; i++)
if(a[i] == 1) ans = (ans + s[i]) % mod;
else ans = (ans + s[i] * (k + 1) % mod) % mod;
printf("%lld\n",ans);
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--){
scanf("%lld %lld %lld",&l,&r,&k);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: