Counting Divisors
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1612 Accepted Submission(s): 595
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 :
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) .
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
Recommend
liuyiding
官方题解:
设n=p1c1p2c2...pmcm,则d(nk)=(kc1+1)(kc2+1)...(kcm+1)。
枚举不超过√r的所有质数p,再枚举区间[l,r]中所有p的倍数,将其分解质因数,最后剩下的部分就是超过√r的质数,只可能是0个或1个。
时间复杂度O(√r+(r−l+1)loglog(r−l+1))。
一开始想到了这个公式,每次都傻傻的一个一个遍历,后来才想到,首先找到区间内第一个可以被素数整除的数,然后每次除完之后,可以跳这个素数的长度,所指向的那个数必然能被这个素数整除,mdzz。#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define ll long long
using namespace std;
const int maxn=1e6+5;
const long long mod=998244353;
ll prim[maxn];
ll p[maxn];
ll num[maxn];
ll ans[maxn];
int sz;
void init() {
for(int i = 2; i <maxn; ++i) {
if(!p[i]) prim[sz++] = i;
for(int j = 0; j < sz; ++j) {
int t = i * prim[j];
if(t >= maxn) break;
p[t] = true;
if(i%prim[j] == 0) break;
}
}
// for(int i=0;i<sz;i++)
// printf("%d ",prim[i]);
}
int main(){
freopen("test.txt","r",stdin);
int t;
int i,j;
ll l,r,k,cnt;
init();
scanf("%d",&t);
while(t--){
scanf("%lld %lld %lld",&l,&r,&k);
for(i=0;i<=r-l;i++){
num[i]=i+l;
ans[i]=1;
}
// for(j=0;j<=r-l;j++)
// printf("%lld ",num[j]);
// printf("\n");
// for(j=0;j<=r-l;j++)
// printf("%lld ",ans[j]);
// printf("\n");
for(i=0;prim[i]*prim[i]<=r;i++){
//printf(" %d\n",prim[i]);
// for(j=0;j<=r-l;j++){
// if(num[j]%prim[i]==0){
// //printf("%lld %d\n",num[j],prim[i]);
// break;
// }
// }
j=0;
ll left=l%prim[i];
if(left!=0)
j=prim[i]-left;
else
j=0;
while(j<=r-l){
cnt=0;
while(num[j]%prim[i]==0){
cnt++;
num[j]/=prim[i];
}
//cnt++;
cnt%=mod;
ans[j]=(ans[j]*(cnt*k+1))%mod;
//ans[j]%=mod;
j+=prim[i];
}
// for(j=0;j<=r-l;j++)
// printf("%lld ",num[j]);
// printf("\n");
// for(j=0;j<=r-l;j++)
// printf("%lld ",ans[j]);
// printf("\n");
}
for(i=0;i<=r-l;i++){
if(num[i]!=1){
ans[i]*=(k+1);
ans[i]%=mod;
num[i]=1;
}
}
cnt=0;
for(i=0;i<=r-l;i++){
cnt+=ans[i];
cnt%=mod;
}
printf("%lld\n",cnt);
}
return 0;
}