2017 Multi-University Training Contest - Team 4 Counting Divisors

本文介绍了一种高效的算法,用于筛选素数并分解指定区间内整数的因子。通过预处理素数并利用这些素数来分解区间[L,R]内的数的因子,大大减少了计算量。该算法特别适用于因子较少的大数处理。

这个题目不算太难,就是几个关键步骤。

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值