ACM-ICPC 2018 南京赛区网络预赛 J. Sum (欧拉筛法+规律)

https://nanti.jisuanke.com/t/30999

题意:

f(i):能拆成两个数的乘积,并且这两个数要求没有平方因子。

最后求f(1)+f(2)+f(3)+...f(n)。

 

思路:

我们可以发现素数的f 为2,每个大于2的数都能拆成若干个素数相乘,如果一个素数出现三次,那这个数的f肯定为0,没有相同素数时为2^{p}(p为因数个数),否则为2^{n}/2^{p}(n为不同因子的个数,p为相同因子的对数),知道这个就能用欧拉筛法求解

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e7+10;
bool prim[maxn];
int pri[maxn];
int  f[maxn];
ll ans[maxn];
void init()
{
    f[1]=1;
    memset(prim,false,sizeof(prim));
    int cnt=0;
    for(int i=2;i<maxn;i++)
    {
        if(!prim[i])
            pri[cnt++]=i,f[i]=2;
        for(int j=0;j<cnt&&pri[j]*i<maxn;j++)
        {
            prim[i*pri[j]]=true;
            if(i%pri[j]==0)
            {
                if(i%(pri[j]*pri[j])==0)
                    f[i*pri[j]]=0;
                else f[i*pri[j]]=f[i]/2;
                break;
            }
            else f[i*pri[j]]=f[i]*2;
        }
    }
}
int main()
{
    init();
    ans[0]=0;
    for(int i=1;i<maxn;i++)
    ans[i]=ans[i-1]+f[i];
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        printf("%lld\n",ans[n]);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章