[博客迁移][题解] HDU 6069

193 阅读2分钟

from HDU 6069 题解


题目:acm.hdu.edu.cn/showproblem…

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 :

\begin{eqnarray*} \left(\sum_{i=l}^r d(i^k)\right)\bmod 998244353 \end{eqnarray*}

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≤10^{12},r−l≤10^6,1≤k≤10^7).

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(x)表示x的因子的个数,求公式的值

方法:

首先枚举出小于 \sqrt{N} 的素数(N = 10^{12})(注意,代码中的N为10^6)。

接着,根据公式计算结果

公式:若n=p_1^{c_1}p_2^{c_2}...p_m^{c_m}n=p,则d(n^k)=(kc_1+1)(kc_2+1)...(kc_m+1)

代码:

#include<cstdio>
typedef long long ll;
const int N=1000010,P=998244353;
int Case,i,j,k,p[N/10],tot,g[N],ans;ll n,l,r,f[N];
bool v[N];

void work( ll p ){
	// 传入一个素数,对f数组进行检验,如果该素数是其因子,则循环除尽,并更新g数组相应元素
 	for( ll i = l / p * p; i <= r; i += p ) 
 		if(i>=l) {
	    	int o=0;
	    	while( f[i-l] % p == 0 ) 
	    		f[i-l]/=p,o++;
	    	g[i-l] = 1LL * g[i-l] * ( o * k + 1 ) % P;
	  	}
}
int main(){
	// 将小于N的素数存在p数组中
  	for(i=2;i<N;i++){
    	if(!v[i])p[tot++]=i;
	    for(j=0;j<tot&&i*p[j]<N;j++){
	      	v[i*p[j]]=1;
	      	if(i%p[j]==0)break;
	    }
  	}
  
  	scanf("%d",&Case);
	while(Case--){
	    scanf("%lld%lld%d",&l,&r,&k);
	    n=r-l;
	    // f数组存储输入的数,g数组存储对应的答案
	    for(i=0;i<=n;i++)
	    	f[i]=i+l,g[i]=1;

	    // 只需循环到根号r,因为大于等于根号r的数是不可能成为小于r的数的因子的
	    for(i=0;i<tot;i++){
	      	if(1LL*p[i]*p[i]>r)
				break;
	      	work(p[i]);
	    }

	    // 计算结果
	    for( ans = i = 0; i <= n; i++ ) {
	      	if(f[i]>1)
	      		// 如果f[i]大于1,则意味着,之前的所有素数都不是它的因子,那么它自身一定是素数
	      		g[i]=1LL*g[i]*(k+1)%P;
	      	ans=(ans+g[i])%P;
	    }
	    printf("%d\n",ans);
	}
  	return 0;
}