【容斥原理】【poj 2773】Happy 2006

来源:互联网 发布:网络修真小说神作 编辑:程序博客网 时间:2024/06/08 14:28

http://poj.org/problem?id=2773


求第k大与n互质的数,二分+莫比乌斯水过

据说裸用容斥原理可以0ms

对此我表示hehe


我的时间复杂度:O(n+qsqrt(n)logn)

下面的:O(n+qsqrt(n)+qlogn*(2^(logn)))(如果同样是线性筛)

尼玛这根本不是多项式的复杂度啊。

【update】我x我犯逗了2^logn肿么不是多项式。。。。。。?


//#define _TEST _TEST#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>using namespace std;/************************************************Code By willinglive    Blog:http://willinglive.cf************************************************/#define rep(i,l,r) for(int i=(l),___t=(r);i<=___t;i++)#define per(i,r,l) for(int i=(r),___t=(l);i>=___t;i--)#define MS(arr,x) memset(arr,x,sizeof(arr))#define LL long long#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)inline const LL read(){LL r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}/////////////////////////////////////////////////const int N=1000000;int prim[100000],mu[N+10],cnt;bool flag[N+10];int n,k,sq;int a[2000];/////////////////////////////////////////////////void init_prim_mu(){mu[1]=1;rep(i,2,N){if(!flag[i]) prim[++cnt]=i,mu[i]=-1;for(int j=1;j<=cnt && i*prim[j]<=N;j++){flag[i*prim[j]]=1;if(i%prim[j]==0){mu[i*prim[j]]=0;break;}else mu[i*prim[j]]=-mu[i];}}}int cal(int x){int res=0;rep(i,1,*a){res+=x/a[i]*mu[a[i]];}return res;}/////////////////////////////////////////////////void solve(){init_prim_mu();while(~scanf("%d%d",&n,&k)){int l=1,r=1000000000,mid;sq=(int)sqrt((double)n);*a=0;rep(d,1,sq) if(n%d==0){a[++*a]=d;if(d*d!=n) a[++*a]=n/d;}while(l<r){mid=l+r>>1;if(cal(mid)<k) l=mid+1;else r=mid;}printf("%d\n",l);}}/////////////////////////////////////////////////int main(){    #ifndef _TEST    freopen("std.in","r",stdin); freopen("std.out","w",stdout);    #endif    solve();    return 0;}


贴上神奇的裸容斥原理

From:http://blog.163.com/happyliyifan@126/blog/static/37462772201311315033520/


#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>#define N 1005using namespace std;int n , k, K, cnt;int mark[N + 10], prime[N];int a[11];void init(){    cnt = 0;    for(int i = 2; i <= N; i++)    {        if(!mark[i])        {            prime[cnt++] = i;            for(int j = 2 * i; j <= N; j += i)            {                mark[j] = 1;            }        }    }}void getprime(){    int tmp = n;    k = 0;    for(int i = 0; i < cnt && prime[i] * prime[i] <= n; i++)    {        if(tmp % prime[i] == 0)        {            a[k++] = prime[i];            while(tmp % prime[i] == 0)            {                tmp /= prime[i];            }        }    }    if(tmp != 1)    {        a[k++] = tmp;    }}int judge(int num){    int sum = 0;    for(int i = 1; i < (1 << k); i++)    {        int tmp = 1;        int t = 0;        for(int j = 0; j < k; j++)        {            if((1 << j) & i)            {                t++;                tmp = tmp * a[j];            }        }        if(t % 2 == 1)        {            sum += num / tmp;        }        else        {            sum -= num / tmp;        }    }    return num - sum;}int main(){    init();    while(scanf("%d%d", &n, &K) != -1)    {        getprime();        int l = 1, r = 1000000000, mid, ans;        while(l <= r)        {            mid = (l + r) >> 1;            int pt = judge(mid);            if(pt >= K)            {                if(pt == K) ans = mid;                r = mid - 1;            }            else            {                l = mid + 1;            }        }        printf("%d\n", ans);    }}


0 0
原创粉丝点击