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

[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 分解質因數 多校

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章