您的位置:首页 > 其它

【数论】hdu 6069 Counting Divisors

2017-08-07 10:11 483 查看

Counting Divisors
Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)

Total Submission(s): 2815    Accepted Submission(s): 1040

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

题意:d(i):i 的因子个数,给定范围内任意l,r,k 计算如上公式值;
思路:d(i),把 i 分解为质因子的形式,然后各个质因子的幂+1,然后相乘,就是 i 的因子个数;
开一个数组来保存1~1e6的质数,1e6范围内的质数就够用了;
之前的代码是把 l , r 的循环放在外部,质数的循环放在内部,用来求每一个数的不同质因子的个数,这样的复杂度是n*tot(质数的个数)
把质数的循环放在外部的话,可以优化:
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

#define ll long long
#define mod 998244353

const int N=1000006;

int is_prime[N+10],prime[N+10];
int tot=0;
ll ans;

ll l,r,k;

void get_prime()
{
int i,j;
tot=0;
memset(is_prime,false,sizeof(is_prime));
for(i=2; i<N; i++)
{
if(!is_prime[i])
prime[tot++]=i;
for(j=0; (j<tot)&&(i*prime[j]<N); j++)
{
is_prime[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
}
}

ll f
,g
;
void work()
{
for(ll i=l; i<=r; i++)
f[i-l]=i,g[i-l]=1;

for(int i=0; i<tot; i++)
{
if(prime[i]*prime[i]>r) // 优化 ,如果这个素数的平方都大于r,那么l~r没有能够整除这个素数和这个素数之后的所有素数了;
break;
for(ll j=l/prime[i]*prime[i]; j<=r; j+=prime[i]) //优化 ,每一次都是j+=prime[i];
{
if(j>=l)
{
int cnt=0;
while(f[j-l]%prime[i]==0)
{
cnt++;
f[j-l]/=prime[i];
}
g[j-l]=g[j-l]*(cnt*k+1)%mod;
}
}
}

for(ll i=l; i<=r; i++)
{
if(f[i-l]>1)
g[i-l]=g[i-l]*(k+1)%mod;
ans=ans+g[i-l];
if(ans>=mod)
ans%=mod;
}
}

int main()
{
int T;
scanf("%d",&T);
get_prime();

while(T--)
{
ans=0;
scanf("%I64d%I64d%I64d",&l,&r,&k);
work();
printf("%I64d\n",ans%mod);
}
return 0;
}


代码中有 l / prime[i] * prime[i] ,这个代码是找到离 l 最近的,小于等与 l 的,能够整除 prime[i] 的数;
参考队友的思路,代码,≧ ﹏ ≦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu