hdu 2597(容斥原理)
Posted leader_win
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; }
以上是关于hdu 2597(容斥原理)的主要内容,如果未能解决你的问题,请参考以下文章