[2017 Multi-University Training Contest

来源:互联网 发布:英语发音规则 知乎 编辑:程序博客网 时间:2024/06/05 15:10

[2017 Multi-University Training Contest - Team 4] HDU 6069 Counting Divisors


题目链接:

HDU 6069

题目大意:

给定l,r,k 定义d(x)x因子的个数, 求:

(i=lrd(ik))mod998244353


数据范围:

l,r,k(1lr1012,rl106,1k107)


解题思路:

我们将x分解质因数x=px11px22px22...
那么 x因子的个数为 (x1+1)(x2+1)(x3+1)...
因此, 我们可以先线性筛出11012的素数,再把从lr对于每一个质数能整除谁筛出来, 最后大于r 最多只有一个, 单独算一下就好 因为是k次幂, 所以答案应对于每个x1都应该乘以k

代码:

//2017-08-04 13:37//2017-08-04 14:00#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<cstdlib>using namespace std;typedef long long LL;const int MaxN = 1e6;const int pt = 998244353;int T;LL l, r, k;int prime[MaxN + 5];LL num[MaxN + 5], sum[MaxN + 5];int pcnt;bool vis[MaxN + 5];void getprime(){    for(int i = 2; i <= MaxN; i++){        if(!vis[i]) prime[++pcnt] = i;        for(LL j = 1; j <= pcnt && i * prime[j] <= MaxN; j++){            vis[i * prime[j]] = true;            if(i % prime[j] == 0) break;        }    }}int main(){    scanf("%d", &T);    getprime();    while(T--){        scanf("%lld %lld %lld", &l, &r, &k);        for(int i = 1; i <= r - l + 1; i++) num[i] = l + i - 1, sum[i] = 1;        LL tmp = sqrt(r);        for(int i = 1; i <= pcnt; i++){            LL x = l, p = prime[i];            if(p > tmp) break;            if(x % p != 0) x = x + p - x % p;            while(x <= r){                int pos = x - l + 1;                LL cnt = 0;                while(num[pos] % p == 0) cnt++, num[pos] /= p;                sum[pos] = sum[pos] * (cnt * k % pt + 1) % pt;                x += p;            }        }        LL ans = 0;        for(int i = 1; i <= r - l + 1; i++) if(num[i] > 1)            sum[i] = sum[i] * (k + 1) % pt;        for(int i = 1; i <= r - l + 1; i++) ans = (ans + sum[i]) % pt;        printf("%lld\n", ans);    }    return 0;}

标签: HDU 分解质因数 多校

原创粉丝点击