您的位置:首页 > 大数据 > 人工智能

2017 Multi-University Training Contest - Team 4 hdu6069 Counting Divisors

2017-08-04 01:33 435 查看

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6069

题目:

Counting Divisors

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


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  

 

Source 2017 Multi-University Training Contest - Team 4  

 思路:

  首先需要知道:一个数可以用唯一分解定理表示成:n=p1^a1*p2^2......*pn^an

         质约数个数为(a1+1)*(a2+1)*....*(an+1)

  那么n^k的质约数个数为(a1*k+1)*(a2*k+1)*.....*(an*k+1)

  所以这题的关键是求l,r区间每个数的质约数有那些,且次数是多少。

  考虑到:l,r最大为1e12,所以枚举1-1e6内的所有素数后即可知道l,r中每个数的质约数有哪些,同时可以知道次数是多少

  但是直接在1-1e6的素数表内查找l,r中的某个数的素约数的时间复杂度是O(1e6),显然不可行。

  所以可以通过线性筛的思想来求:对于1-1e6的素数,考虑他会在l,r内筛掉哪些数即可。

  因为1e12每个数最多有20左右的质约数,所以时间复杂度是O((r-l)*20)+O(1e5)(质数表大小)

  

#include <bits/stdc++.h>

using namespace std;

#define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int,int> PII;
const double eps=1e-8;
const double pi=acos(-1.0);
const int K=1e6+7;
const int mod=998244353;

LL ql,qr,qk,cnt,ls[K],sum[K],pr[K];
bool pa[K];
void init(void)
{
for(int i=2;i<=1000000;i++)
if(!pa[i])
{
pr[cnt++]=i;
for(int j=i*2;j<=1000000;j+=i) pa[j]=1;
}
}
LL sc(int t)
{
LL ans=0;
for(LL i=ql;i<=qr;i++) sum[i-ql]=1,ls[i-ql]=i;
for(int i=0;i<cnt;i++)
{
for(LL j=max(2LL,(ql+pr[i]-1)/pr[i])*pr[i];j<=qr;j+=pr[i])
{
LL cnt=0;
while(ls[j-ql]%pr[i]==0) ls[j-ql]/=pr[i],cnt++;
sum[j-ql]=(sum[j-ql]*(qk*cnt+1))%mod;
}
}
for(LL i=ql;i<=qr;i++)
{
if(ls[i-ql]!=1) sum[i-ql]=(sum[i-ql]*(qk+1))%mod;
ans+=sum[i-ql];
if(ans>=mod) ans-=mod;
}
return ans;
}

int main(void)
{
//freopen("in.acm","r",stdin);
int t;scanf("%d",&t);
init();
while(t--)
{
scanf("%lld%lld%lld",&ql,&qr,&qk);
printf("%lld\n",sc(t));
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐