zoukankan      html  css  js  c++  java
  • 【XSY1580】Y队列 容斥

    题目大意

      给你(n,r),求第(n)个不能被表示为(a^b(2leq bleq r))的数

      (nleq 2 imes {10}^{18},rleq 62)

    题解

      我们考虑二分,求(leq m)的不能被表示为(a^b)的数(f(m))

      我们先忽略(1)

      我们钦定能被表示为(a^2,a^3,a^5)(b)为质数的数,贡献为(lfloorsqrt[2]{m} floor-1,lfloorsqrt[3]{m} floor-1cdots),这样也会包含当(b)为合数时的情况,例如(a^4={(a^2)}^2)

      但我们算多了,例如(a^3=b^2=c^6),所以我们要减掉(b)为两个不同的质数的积的情况,即(lfloorsqrt[6]{m} floor-1,lfloorsqrt[10]{m}-1 floorcdots)

      然后加上(b)为三个不同的质数的积的情况,减掉(b)为四个不同的质数的积的情况……

      我们发现(b=x)时容斥系数为(mu(x))

      当(b>62)(lfloorsqrt[b]{m} floor=1),所以不用继续往下算了

      还有,开(n)次根号可以用pow,不过要传long double参数进去,不然就会炸精度。

      但是这样子还会tle,因为有(30000)组数据

      我们发现(f(x)approxsqrt{x})

      我们计算出(f(n)),然后每次把(n)加上(n-f(n)),可以很快得到答案

      时间复杂度:(O(???))

      反正能过且常数巨大就对了

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef long double ld;
    int p[100];
    int u[100];
    int b[100];
    int mx[100];
    int cnt;
    ll n;
    int k;
    ll fp(ll a,ll b)
    {
    	ll s=1;
    	while(b)
    	{
    		if(b&1)
    			s=s*a;
    		a=a*a;
    		b>>=1;
    	}
    	return s;
    }
    ll calc(ll n,ll x)
    {
    	ll s=floor(ld(pow(ld(n),ld(1)/x)));
    	return s;
    }
    ll count(ll x)
    {
    	int i;
    	ll s=0;
    	ll nw;
    	for(i=1;i<=62;i++)
    		if(mx[i]<=k&&u[i])
    		{
    			nw=calc(x,i)-1;
    			if(!nw)
    				break;
    			s+=u[i]*nw;
    		}
    	return s;
    }
    void solve()
    {
    	scanf("%lld%d",&n,&k);
    	ll t=n;
    	ll s=count(t);
    	while(1)
    	{
    		t+=n-s;
    		s=count(t);
    		if(s==n)
    			break;
    	}
    	printf("%lld
    ",t);
    }
    int main()
    {
    	int i,j;
    	cnt=0;
    	memset(b,0,sizeof b);
    	u[1]=1;
    	mx[1]=1;
    	for(i=2;i<=62;i++)
    	{
    		if(!b[i])
    		{
    			p[++cnt]=i;
    			mx[i]=i;
    			u[i]=-1;
    		}
    		for(j=1;j<=cnt&&i*p[j]<=62;j++)
    		{
    			b[i*p[j]]=1;
    			mx[i*p[j]]=mx[i];
    			if(i%p[j]==0)
    			{
    				u[i*p[j]]=0;
    				break;
    			}
    			u[i*p[j]]=-u[i];
    		}
    	}
    	int t;
    	scanf("%d",&t);
    	while(t--)
    		solve();
    	return 0;
    }
    
  • 相关阅读:
    tkinter_战队数据查询系统
    python_tkinter组件
    python_tkinter基本属性
    python_tkinter组件摆放方式
    python_推导式
    python_装饰器
    python_模块1
    python_生成随机验证码
    linux基础_使用指令3
    linux部署django项目流程(全)
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8511063.html
Copyright © 2011-2022 走看看