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