1. 程式人生 > >UESTC 618 無平方因子數 (容斥 + 莫比烏斯反演)

UESTC 618 無平方因子數 (容斥 + 莫比烏斯反演)

無平方因子數

Time Limit: 4000/2000MS (Java/Others)   

Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
無平方因子數即對於任意一個素數p,p2都不會整除那個數,如1 , 5=5 , 15=3×5都是無平方因子數,而20=22×5不是。現在給定一個n (1≤n<1012) ,求區間[1,n]中無平方因子數的個數。

Input
第一行有個整數T,代表資料組數(T≤10)

接下來有T行,每行有個整數n (1≤n<1012)

Output
輸出T行,每行輸出一個整數代表區間[1,n]內的無平方因子數的個數。

Sample Input   
3
1
10

30

Sample Output

1
7

19


Source

UESTC Training for Math

題目分析:又是無平方因子數,比BZOJ那題簡單很多,直接算就行了,參照BZOJ 2440

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int const MAX = 1e6 + 5;
int mob[MAX], p[MAX];
bool prime[MAX];

void Mobius()
{
    int pnum = 0;
    memset(prime, true, sizeof(prime));
    mob[1] = 1;
    for(int i = 2; i < MAX; i++)
    {
        if(prime[i])
        {
            p[pnum ++] = i;
            mob[i] = -1;
        }
        for(int j = 0; j < pnum && i * p[j] < MAX; j++)
        {
            prime[i * p[j]] = false;
            if(i % p[j] == 0)
            {
                mob[i * p[j]] = 0;
                break;
            }
            mob[i * p[j]] = -mob[i];
        }
    }
}

ll cal(ll n)
{
    ll cnt = 0;
    for(ll i = 1; i * i <= n; i++)
        cnt += (ll) mob[i] * (n / (i * i));
    return cnt;
}

int main()
{
    Mobius();
    int T;
    scanf("%d", &T);
    while(T --)
    {
        ll n;
        scanf("%lld", &n);
        printf("%lld\n", cal(n));
    }
}