【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=6069
题目意思
给你了l,r,k。问你i从l到r,i^k因子个数的总和
解题思路
根据约数个数定理:n=p1^a1×p2^a2×p3^a3*…*pk^ak
,n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)
.(p为质数)
若i=p1^a1×p2^a2×p3^a3*…*pk^ak,则i^K=p1^(a1*K)×p2^(a2*K)×p3^(a3*K)*…*pk^(ak*K)
,i^K的约数的个数就是(a1*K+1)(a2*K+1)(a3*K+1)…(ak*K+1)
,由此可推出质数的因子数为k+1
。质数的a次方就有(a*k)+1
个因子
这样只要把区间里的合数分为质数乘积就可以了。(如:12=2*2*3
,他的因子数就为(2*1+1)*(1+1)=6
代码部分
///发现写的是没大佬的好把大佬的代码借用了
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=1e6+10;
const int mod=998244353;
int tot,t;
ll l,r,k,ans,cnt[maxn],q[maxn],pri[maxn];
bool vis[maxn];
void init() ///筛选法质数打表
{
for(int i=2; i<maxn; i++)
{
if(!vis[i])
pri[tot++]=i;
for(int j=0; j<tot; j++)
{
int k=i*pri[j];
if(k>maxn)break;
vis[k]=1;
}
}
}
int main()
{
scanf("%d",&t);
init();
while(t--)
{
scanf("%lld%lld%lld",&l,&r,&k);
ans=0;
if(l==1) ans++,l++;
for (ll i=0; i<=r-l; i++)
{
cnt[i]=1; ///存对应的l+i里有多少个质数
q[i]=l+i; ///存下标
}
for (ll i=0; pri[i]*pri[i]<=r; i++)
{
ll j=l/pri[i]+(l%pri[i]!=0); ///找到这个质数第一个出现的给定区间的倍数
for (j=j*pri[i]; j<=r; j+=pri[i]) ///从区间里第一个质数倍数到最后一个
{
ll tmp=0;
while (q[j-l]%pri[i]==0)
{
q[j-l]/=pri[i]; ///求可以分解多少个pre[i],
tmp++;
}
cnt[j-l]*=(tmp*k)%mod+1; ///tmp个pir[i]所以cnt[j-1]有(tmp*k)%mod+1个质数
cnt[j-l]%=mod;
}
}
for (ll i=0; i<=r-l; i++)
{
if (q[i]!=1) ///可能残留大于根号r的一个质数
ans+=((k+1)*cnt[i])%mod;
else ans+=cnt[i];
ans%=mod;
}
printf("%lld\n",ans);
}
}