这个题目不算太难,就是几个关键步骤。
1.进行筛选素数,这里当然不能到10^12 要开方,最后对每个数而言,大于他根号倍的素数最对就一个,也可能没有。
2.我们已经把要用素数求出来了,如果直接对L-R的每个数进行分解的话,对于一些因子比较少的数来说会进行大量无用操作。
这里我们用倍数进行筛选,用prime【】表示素数数组,用ar【】表示LR的每个元素,枚举prime数组,把ar【】里面是他倍数的元素
进行分解因子。最后ar里面几乎都是1,如果不为1那么表示他有大于根号他的元素,进行*(K+1)即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const long long mod=998244353;
vector<long long> prime;
bool isprime[1000005];
long long little[1000005];
long long ar[1000005];
int main()
{
//freopen("fuck.txt","r",stdin);
int T;
for(int i=1;i<=1000000;i++)
isprime[i]=1;
for(int i=2;i<=1000000;i++)
{
if(isprime[i])
{
int pos=2;
while(pos*i<=1000000)
{
isprime[pos*i]=false;
pos++;
}
}
}
for(int i=2;i<=1000000;i++)
if(isprime[i])
prime.push_back(i);
scanf("%d",&T);
while(T--)
{
long long l,r,k,ans=0;
scanf("%lld%lld%lld",&l,&r,&k);
for(int i=0;i<=1000004;i++)
little[i]=1;
for(int i=0;i<=r-l;i++) ar[i]=l+i;
for(long long i=0;i<prime.size();i++)
{
long long pe=l%prime[i]==0?l:l-(l%prime[i])+prime[i];
for(long long j=pe;j<=r;j+=prime[i])
{
//long long loop=ar[j-l],sum=0;
long long sum=0;
while(ar[j-l]%prime[i]==0)
{
ar[j-l]/=prime[i];
sum++;
}
little[j-l]*=(k*sum+1);
little[j-l]%=mod;
//ar[j-l]=loop;
}
}
for(int i=0;i<=r-l;i++)
{
if(ar[i]!=1)
{
little[i]*=(k+1);
little[i]%=mod;
}
}
for(long long i=0;i<=r-l;i++)
{
ans+=little[i];
ans%=mod;
}
printf("%lld\n",ans);
}
return 0;
}
本文介绍了一种高效的算法,用于筛选素数并分解指定区间内整数的因子。通过预处理素数并利用这些素数来分解区间[L,R]内的数的因子,大大减少了计算量。该算法特别适用于因子较少的大数处理。

127

被折叠的 条评论
为什么被折叠?



