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

 

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