2016 UESTC Training for Math Problem F-粗心的谭爷(线性筛素数)

F - 粗心的谭爷

Time Limit: 1000/1000MS (Java/Others)    Memory Limit: 262144/262144KB (Java/Others)

谭爷喜欢把整数分解质因数,如12=22∗3

,1024=210,特别地,1=1

有一天谭爷心血来潮,把1

n

所有整数的分解形式写在纸上,然后计算它们的和。

但粗心的谭爷把公式中的幂运算的指数看成了连接在底数后面的数字,如把22∗3

看成了22∗3=66,把210看成了210=210

,因此结果与真实答案大相径庭。

谭爷没有发现这一点,并愚蠢的继续算下去。

坐在谭爷旁边的你看不下去了,写个程序帮谭爷算出他最终得到的结果。

Input

输入一个整数n

,1≤n≤107

Output

输出谭爷算出来的结果。

解题思路:

利用线性筛素数的做法,

考虑两种情况:

(1)i%prime[j]==0:

则对应的i*prime[j]的times[i*prime[j]]++;

(2) i%prime[j]!=0;

则i不含prime[j]这个因子;

则ans[i*prime[j]]=ans[i]*calc(minprime[i],times[i]);

代码:

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10000005
long long prime[MAXN/2],times[MAXN],minprime[MAXN];//prime记录素数,times记录i被最小的质因子筛了多少次,minprime记录最小的质因子; 
long long ans[MAXN];//记录看错后的数字 
bool flag[MAXN];//记录有没有被筛 
long long calc(long long num,long long t)
{
	if(t==1)
	return num;
	else if(t>1&&t<10)
	return num*10+t;
	else if(t>=10&&t<100)
	return num*100+t;
}
int main()
{
	long long n,t=0;
	long long sum=1;
	long long i,j;
	memset(flag,false,sizeof(flag));
	scanf("%lld",&n);
	for(i=2;i<=n;i++)
	{
		if(!flag[i])//对于素数,可以直接考虑; 
		{
			prime[t++]=i;
			minprime[i]=i;
			ans[i]=1;
			times[i]=1;
		}
		for(j=0;j<t&&prime[j]*i<=n;j++)
		{
			flag[prime[j]*i]=true;
			minprime[prime[j]*i]=prime[j];
			if(i%prime[j]!=0)
			{
				ans[i*prime[j]]=ans[i]*calc(minprime[i],times[i]);
				times[i*prime[j]]=1;
			}
			else
			{
				ans[i*prime[j]]=ans[i];
				times[i*prime[j]]=times[i]+1;
				break;
			}
		}
		sum+=ans[i]*calc(minprime[i],times[i]);//由于之前只是计算了非最小质因子的结果,所以还要加上一项; 
	}
	printf("%lld",sum);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值