《HDU-2204》

容斥原理:ans = 指数为一个质数 U 指数为两个质数 U 指数为3个指数。

如果为4个质数即2 * 3 * 5 * 7 > 60。那么这个数肯定超过了 n,所以最多只需要枚举到三个质数。

这里指数一定为不一样的质数,因为如果一样就变成了x * x = x ^ 2。

即y ^ (x * x) = y ^ x ^ 2 = (y ^ x) ^ 2。

那么他一定被包含在了指数为2的情况中。

从此可见,若指数不为质数 = t ^ (x * y)。那么这个数就可以表示为 (t ^ x) ^ y。

那么他就会被包含在了指数为y的方案中,所以我们只需要统计所有指数为质数的情况。

对于区间[1,n]。里面有多少指数为k的个数 = n ^ (1 / k)。

然后我们容斥即可。

有容斥原理可知ans = 指数为一个质数的 - 指数为两个质数的 + 指数为三个质数的。

#include<iostream>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<math.h>
#include<stack>
#include<map>
#include<limits.h>
#include<vector>
#include<string.h>
#include<string>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
const int N = 65;
const int M = 1e5 + 5;
const LL Mod = 199999;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;

bool vis[N];
int prime[N],tot = 0,ans[N];
void init() {
    for(int i = 2;i < N;++i) {
        if(!vis[i]) {
            prime[++tot] = i;
        }
        for(int j = 1;j <= tot && prime[j] * i < N;++j) {
            vis[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
int main() {
    init();
    LL n;
    while(cin >> n) {
        memset(ans,0,sizeof(ans));
        for(int i = 1;i <= tot;++i) {
            LL ma = pow(1.0 * n,1.0 / prime[i]);
            ans[1] += ma - 1;
        }
        for(int i = 1;i <= tot;++i) {
            for(int j = i + 1;j <= tot;++j) {
                LL ta = prime[i] * prime[j];
                ans[2] += pow(1.0 * n,1.0 / ta) - 1;
            }
        }
        for(int i = 1;i <= tot;++i) {
            for(int j = i + 1;j <= tot;++j) {
                for(int k = j + 1;k <= tot;++k) {
                    LL ta = prime[i] * prime[j] * prime[k];
                    ans[3] += pow(1.0 * n,1.0 / ta) - 1;
                }
            }
        }
        printf("%lld\n",ans[1] - ans[2] + ans[3] + 1);//1也算
    } 



    system("pause");
    return 0;
}
View Code

 

posted @ 2021-05-31 21:31  levill  阅读(36)  评论(0编辑  收藏  举报