hdu6069 Counting Divisors 晒区间素数

/**
题目:hdu6069 Counting Divisors
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6069
题意:求[l,r]内所有数的k次方的约数个数之和。

思路:
用(1+e1)*(1+e2)*...*(1+en)的公式计算约数个数。
素数筛出[l,r]内的素因子,然后直接计算结果。(一开始我用vector存起来,之后再处理,结果超时,
时间卡的很紧的时候,vector也会很占用时间。)


*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const int maxn = 1e6+10;
bool is_prime_small[maxn];
vector<int> v[maxn];
int prime[maxn], z;
LL value[maxn], cnt[maxn];
void init()
{
    for(int i = 2; i<=1000000; i++) is_prime_small[i] = true;
    z = 0;
    for(int i = 2; i<=1000000; i++){
        if(is_prime_small[i]){
            z++;
            prime[z] = i;
        }
        for(int j = 1; j <= z; j++){
            if((LL)i*prime[j]>=1000000){
                break;
            }
            is_prime_small[i*prime[j]] = false;
            if(i%prime[j]==0) break;
        }
    }
}
void segment_sieve(LL a,LL b,LL k)  //[a,b)
{

    for(int i = 0; i < b-a; i++) value[i] = i+a, cnt[i] = 1;
    int num;
    for(int i = 1; (LL)prime[i]*prime[i]<b&&i<=z; i++){
        for(LL j = max((LL)prime[i],(a+prime[i]-1)/prime[i])*prime[i]; j < b; j+=prime[i]){
            num = 0;
            while(value[j-a]%prime[i]==0){
                num++; value[j-a]/=prime[i];
            }
            cnt[j-a] = cnt[j-a]*(num*k+1)%mod;
        }
    }
}
LL solve(LL a,LL b,LL k)
{

    LL ans = 0;
    for(int i = 0; i < b-a; i++){
        if(value[i]>1){
          cnt[i] = cnt[i] * (k+1) % mod;
        }
        ans = (ans + cnt[i])%mod;
    }

    return ans;
}
int main()
{
    int T;
    cin>>T;
    init();
    LL l, r, k;
    while(T--){
        scanf("%lld%lld%lld",&l,&r,&k);
        if(l==r&&l==1){
            printf("1
"); continue;
        }
        int flag = 0;
        if(l==1){
            l++;
            flag = 1;
        }
        segment_sieve(l,r+1,k);
        printf("%lld
",(solve(l,r+1,k)+flag)%mod);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiaochaoqun/p/7283884.html