hdu 2597(容斥原理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5297

题意:给出n和r,求数列Y的第n个元素是多少。其中数列Y是正整数数列去除a^b(2<=b<=r)后的数

分析:

我的天啊,出一个数n,则1~n以内的正整数必定会有被去除的(假设被去除x1个),则这n个数中只有(n-x1)个数在Y数列中;如果想得到n个数在Y数列中,那么我们至少要在这n个数后面加上x1个数,设n1=n+x1,则在1~n1内的数有多少在Y数列中呢(假设有m个在Y数列中,去除了x2个)?如前面所说,在1~n1内的数最多有n个数在Y数列中(即m<=n),此时判断m与n是否相等。如果相等,则Y数列中第n个数为(n+x1);如果不相等,则继续在(n+x1)数后面再加x2个数,继续判断……一直加到某个数M,使得1~M内的数在Y数列中刚好有n个。关键在于如何求解在小于n的数里内有多少个数可以表示为a^b;

这时就要用到容斥原理了;

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <functional>
using namespace std;
int a[]={-2,-3,-5,-7,-11,-13,-17,-19,-23,-29,-31,-37,-41,-43,-47,-53,-59,-61,-67};
//选择负数是方便进行容斥原理
vector<int>G;
void get_su(int r){
    for(int i=0;abs(a[i])<=r;i++){
        int s=G.size();
        for(int j=0;j<s;j++){
            if(abs(a[i]*G[j])<=63){
                G.push_back(a[i]*G[j]);
            }
        }
        G.push_back(a[i]);
    }
}
//把小于r的数进行容斥
long long sm(long long x){
    if(x==1)return 0;
    int s=G.size();
    long long ans=x;
    for(int i=0;i<s;i++){
        long long tmp=(long long)(pow(x+0.5,1/(double)(abs(G[i]))))-1;
        if(G[i]<0)ans-=tmp;
        else ans+=tmp;
    }
    return ans-1;
}
//求解每一步的值
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int r;
        long long n;
        scanf("%I64d%d",&n,&r);
        G.clear();
        get_su(r);
        long long tmp;
        long long ans=n;
        while(1){
            tmp=sm(ans);
//            cout<<tmp<<endl;
            if(tmp==n)break;
            ans+=n-tmp;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
时间: 2024-08-15 21:23:07

hdu 2597(容斥原理)的相关文章

hdu 1695 容斥原理或莫比乌斯反演

GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5310    Accepted Submission(s): 1907 Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y)

HDU 4336 容斥原理 || 状压DP

状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1; F(S)表示取状态为S的牌的期望次数,Sum表示什么都不取得概率,p(x1)表示的是取x1的概率,最后要加一因为有又多拿了一次.整理一下就可以了. 1 #include <cstdio> 2 const int Maxn=23; 3 double F[1<<Maxn],p[Maxn]; 4 int n; 5 int main() 6

hdu 4135 容斥原理

又搞了一道容斥原理. 题目:求[1,n]区间对m互质的数有多少个? #include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define LL __int64 const int maxn = 1e5+8; LL a[maxn],cn,numpri[maxn],vis[maxn]

HDU 1796 容斥原理

How many integers can you find Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7439    Accepted Submission(s): 2200 Problem Description Now you get a number N, and a M-integers set, you should

HDU 4059 容斥原理+快速幂+逆元

题目求1-n中与n互质的数的4次方之和,即S=a1^4+a2^4+……; a1,a2……均小于等于n且与n互质. 先求出1^4+2^4+……n^4然后减去与n不互质的数的4次方. 必然要先要用到4次方的求和公式.接下来简单的证明一下,这里前提是你知道3次方的公式,如果不会照下面的模式可以利用2次公式推出3次公式 (x+1)^5=x^5+5*x^4+10*x^3+10*x^2+5*x+1; 则 1=1; 2^5=(1+1)^5=1^5+5*1^4+10*1^3+10*1^2+5*1^1+1; 3^

hdu 3501 容斥原理或欧拉函数

Calculation 2 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2181    Accepted Submission(s): 920 Problem Description Given a positive integer N, your task is to calculate the sum of the positiv

hdu 1796(容斥原理+状态压缩)

How many integers can you find Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6630    Accepted Submission(s): 1913 Problem Description Now you get a number N, and a M-integers set, you should

hdu 5514 容斥原理

hdu 5514 题意: 有 n 只青蛙,一开始都在 0 点.有一堆围成一圈的石子,石子的编号是从 0 ~ (m-1). 所有青蛙只能顺时针跳,每个青蛙可以一次跳a[i]格.问这些青蛙踩过的石子的编号总和是多少? tags:  容斥经典题. 对 m 分解因子,对每个因子求贡献. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000")

hdu 5297 容斥原理

很容易想到我们需要这样一个函数f(n)表示的是1~n的数字中在y sequence中的个数,于是可以想到用容斥来做,先假设答案是n然后计算n中y sequence的个数,然后n加上不够的,继续判断,一直迭代求出答案. 小技巧:预处理的时候素数设为负数方便判断容斥的时候是应该加还是减. 1 #include <iostream> 2 #include <cstring> 3 #include <vector> 4 #include <cstdio> 5 #in