Hdu 6069 Counting Divisors【素數區間篩+預處理素因子分解】
阿新 • • 發佈:2019-02-02
Counting Divisors
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 3150 Accepted Submission(s): 1175
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
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≤10
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】內,D(i^k)的和。
思路:
我們知道,求D(i)可以將數字i進行素因子分解,我們有:i=p1^ans1+p2^ans2+p3^ans3+p4^ans4+...........計算D(i)=(ans1+1)*(ans2+1)*(ans3+1)*.................
我們現在要求D(i^k)的話,結果是等比例增長的,那麼D(i^k)=(ans1*k+1)*(ans2*k+1)*(ans3*k+1)*.................
迴歸問題,觀察到R-L<=1e6的,那麼我們根據熟知的理論,我們將根號R以內的素數預處理出來,然後預處理篩法處理出所有數字的素因子分解的情況即可。
值得注意的一點是,預處理區間素數和區間內素因子分解的結果之後,我們可能有紕漏,也就是會有數字num,不斷除素因子之後 ,可能最終剩下的數不是1.可能是一個大於根號R的素數,那麼在記錄答案的時候統計起來即可。
Ac程式碼:
#include<stdio.h>
#include<string.h>
using namespace std;
#define ll long long int
#define Maxn 1005000
int tot;
int Is_or[1105000];
ll prime[1105000];
ll ans[1105000];
ll num[1105000];
ll mod=998244353;
void init()
{
tot=0;
memset(prime,0,sizeof(prime));
memset(Is_or,0,sizeof(Is_or));
for(int i=2;i<=Maxn;i++)
{
if(Is_or[i]==0)
{
prime[tot++]=i;
for(int j=i*2;j<=Maxn;j+=i)
{
Is_or[j]=1;
}
}
}
}
void Div(ll L,ll R,ll k)
{
for(int i=0;i<=R-L;i++)
{
ans[i]=1;
num[i]=i+L;
}
for(ll i=0;i<tot;i++)
{
ll b=L/prime[i];
while(b*prime[i]<L||b<=1)b++;
for(ll j=b*prime[i];j<=R;j+=prime[i])
{
ll cnt=0;
while(num[j-L]%prime[i]==0)cnt++,num[j-L]/=prime[i];
ans[j-L]*=(cnt*k+1);
ans[j-L]%=mod;
}
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
ll l,r,k;
scanf("%lld%lld%lld",&l,&r,&k);
Div(l,r,k);
ll output=0;
for(ll i=0;i<=r-l;i++)
{
if(num[i]!=1)output+=ans[i]*(k+1);
else output+=ans[i];
output%=mod;
}
printf("%lld\n",output);
}
}