Counting Divisors
http://acm.hdu.edu.cn/showproblem.php?pid=6069
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 4338 Accepted Submission(s): 1558
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 :
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
思路
C++代码
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1000006;
const int mod=998244353;
int prime[N+1];
ll a[N+1],sum[N+1];//a[i]存放数i+l sum[i]存放d((i+l)^k)
//欧拉筛法,求出n以内的素数,并存放在prime数组中
void maketable(int n)
{
for(int i=2;i<=n;i++)
{
if(!prime[i])
prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&prime[j]<=n/i;j++)
{
prime[prime[j]*i]=1;
if(i%prime[j]==0)
break;
}
}
}
//区间筛法
ll solve(ll l,ll r,ll k)
{
for(int i=0;i<=r-l;i++)
{
a[i]=i+l;
sum[i]=1;//初始化sum[i]=1,因为至少有一个因子1
}
for(int i=1;i<=prime[0];i++)
{
ll s=(l-1)/prime[i]+1;
ll e=r/prime[i];
for(ll j=s;j<=e;j++)
if(j>1)
{
//j*prime[i]是合数,cnt统计此合数有多少个质因子prime[i]
int cnt=0,pos=j*prime[i]-l;
while(a[pos]%prime[i]==0)
{
cnt++;
a[pos]/=prime[i];
}
sum[pos]=sum[pos]*((cnt*k+1)%mod)%mod;//加上此质因子的贡献
}
}
//进行求和
ll ans=0;
for(int i=0;i<=r-l;i++)
{
if(a[i]!=1) sum[i]=sum[i]*(k+1)%mod;//数i+l是一个素数
ans=(ans+sum[i])%mod;
}
return ans;
}
int main()
{
int t;
ll l,r,k;
maketable(N);
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&l,&r,&k);
printf("%lld\n",solve(l,r,k));
}
return 0;
}