hdu 6069 区间素数+思维

Counting Divisors

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 4021    Accepted Submission(s): 1456


 

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

 


题意:

       函数d(x)表示x的所有因子的数量(包括1和自己),现在给你l,r,k。要你求(\sum _{i=l}^{r}d(i^{k}))取模 

       

做法:

       如果没有k次这个条件,可以联想到母函数。如果x=p_{1}^{a_{1}}p_{2}^{a_{2}}p_{3}^{a_{3}}....p_{n}^{a_{n}},那么d(x)=(1+a_{1})(1+a_{2})(1+a_{3})...(1+a_{n}),因为每个因子都可以选择不取,也可以选择取多少,相乘就是要求的因子数量了。如果碰到质数,那么就是a1就是1。

       但是本题中对每个数又加了k次,相当于把x=p_{1}^{a_{1}}p_{2}^{a_{2}}p_{3}^{a_{3}}....p_{n}^{a_{n}}变成了x^{k}=p_{1}^{a_{1}*k}p_{2}^{a_{2}*k}p_{3}^{a_{3}*k}....p_{n}^{a_{n}*k},只要把你算到的a_{i}乘上k就好了。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int maxn=1000005;
ll prime[maxn],numprime;
bool vis[maxn];
ll ans[maxn],val[maxn];
void init(){
    for(int i=2;i<maxn;i++){
        if(!vis[i])prime[++numprime]=i;
        for(int j=1;j<=numprime&& prime[j]*i<maxn;j++){
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
void solve(ll l,ll r,ll k){
    for(ll i=l;i<=r;i++){
        ans[i-l]=1;  val[i-l]=i;
    }
    for(ll i=1;i<=numprime&&prime[i]<=r;i++){
        ll now=prime[i],fir=(l/prime[i]+(l%prime[i]?1:0))*prime[i];
        for(ll j=fir;j<=r;j+=now){
            ll cnt=0;
            while(val[j-l]%now==0){
                cnt++;  val[j-l]/=now;
            }
            ans[j-l]=((1+cnt*k)%mod*ans[j-l])%mod;
        }
    }
    ll sum=0;
    for(ll i=l;i<=r;i++){
        if(val[i-l]!=1)  ans[i-l]=(1+k)*ans[i-l]%mod;
        sum=(sum+ans[i-l])%mod;
    }
    printf("%lld\n",sum);
}
int main(){
    init();
    int t;
    cin>>t;
    while(t--){
        ll l,r,k;
        scanf("%lld%lld%lld",&l,&r,&k);
        solve(l,r,k);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值