hdu2204_Eddy's爱好_容斥原理

题意

求1到N范围内能表示为 M^k 的数的数量,k > 1。

思路

设 pi 为质数;

Ai 为具有某性质的数的集合,性质:x∈Ai,x = M^pi   [   x = M^ (p1^ t1 * p2 ^ t2 * ... pn ^ tn) = M'^p1 , 当t1 > 1时   ]

ans =  |A1 ∪ A2 ... An - 1 ∪ An|

|Ai| = (int) N^(1 / pi)

hint:注意 pow() 精度

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))

using namespace std;
typedef long long ll;
const double eps = 1e-8;
int prime[100] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59};
ll n, ans;
void dfs(int prs, ll q, int cnt)
{
    if (cnt == 3)
        return;

    for (int i = prs + 1; i < 17; i++)
    {
        ll tmp = prime[i] * q;

        if (tmp <= 60)
        {
            ll p = pow(1.0 * n, 1.0 / tmp);
            /**
            处理精度
            */
            p++;
        
            double t;
            while ((t = pow(1.0 * p, 1.0 * tmp)) > n && fabs(n - t) > eps)
                p--;

            if (p > 1)
            {
                ans += ((cnt & 1) ? (-1) : 1) * (p - 1);

            }


            dfs(i, tmp, cnt + 1);

        }

    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE


    while (scanf("%lld", &n) != EOF)
    {
        ans = 0;
        dfs(-1, 1, 0);
        cout << ans + 1 << endl;

    }



    return 0;
}

猜你喜欢

转载自blog.csdn.net/Anna__1997/article/details/81432069
今日推荐