Counting Divisors
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1527 Accepted Submission(s): 565
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
题意:
给你l,r,k求,在l到r区间中每一个数的k次幂的因子个数和
思路:
根据唯一分解定理,任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积N=P1a1P2a2P3a3......Pnan那么他的因子的个数就为d(N)=(a1+1)*(a2+1)*……*(an+1)那么
d(N^k)=(ka1+1)*(ka2+1)*….*(kan+1)
首先我们先预处理一遍0~√r的素数
然后我们先找到l~r中第一个含有为因子prime[i]的数,对于l必有l=k*prime[i]+r,若r为0则l就为第一个数,若r不为0,那么第一个数一个数(k+1)*prime[i],其中k=l/prime[i],l对prime[i]取模就知道r为不为0了,然后我们这个数进行对prime[i]的分解,就知道他之中有几个prime[i]了
那么下一个含有prime[i]为因子的数就应该是他加上prime[i]这个数,对他进行同样的操作
两遍循环后所有从l~r的数都分解完毕,这些数要么是1要么是一个大于√r的素数,所以对不为1的数我们要多乘一个(k+1)来表示这个素数也参与组合
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=1e6+10;
const int mod=998244353;
int tot,t;
long long prime[maxn];
bool vis[maxn];
long long l,r,k,ans;
long long a[maxn],cnt[maxn];
void init(){//素数筛打表
for(int i=2;i<maxn;i++){
if(!vis[i])
prime[tot++]=i;
for(int j=0;j<tot;j++){
int k=i*prime[j];
if(k>maxn)break;
vis[k]=1;
}
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&l,&r,&k);
ans=0;
if(l==1) ans++,l++;
for(int i=0;i<=r-l;i++)//将范围左移到从0开始
{
a[i]=l+i;
cnt[i]=1;
}
for(int i=0;prime[i]*prime[i]<r;i++)
{
long long j;
if(l%prime[i]==0)//找出范围内第一个含有prime[i]因子的数
j=l/prime[i];
else
j=l/prime[i]+1;
for(j=j*prime[i];j<=r;j+=prime[i])
{
long long tmp=0;
while(a[j-l]%prime[i]==0)
{
a[j-l]/=prime[i];
tmp++;
}
cnt[j-l]*=(k*tmp)%mod+1;
cnt[j-l]%=mod;
}
}
for(int i=0;i<=r-l;i++)
{
if(a[i]!=1) ans+=((k+1)*cnt[i])%mod;//处理剩下的素数因子
else ans+=cnt[i];
ans%=mod;
}
printf("%lld\n",ans);
}
return 0;
}